一、属性绑定
这是最简单的方式,可以在QML中直接绑定C++ 对象的属性。通过在C++ 对象中使用Q_PROPERTY宏定义属性,然后在QML中使用绑定语法将属性与QML元素关联起来。
-
person.h
#include class Person : public QObject { Q_OBJECT /* 使用 Q_PROPERTY 定义交互的属性 */ Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged) Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged) public: explicit Person(QObject *parent = nullptr) : QObject(parent), m_name(""), m_age(0) { } /* 为属性提供 getter 和 setter 方法 */ QString getName() const { return m_name; } void setName(const QString& name) { m_name = name; emit nameChanged(); } int getAge() const { return m_age; } void setAge(int age) { m_age = age; emit ageChanged(); } signals: /* 信号与属性对应,通过信号通知其他对象属性的变化 */ void nameChanged(); void ageChanged(); private: QString m_name; int m_age; };
-
main.cpp
#include #include #include #include "person.h" int main(int argc, char *argv[]) { /* 启用Qt应用程序的高DPI缩放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 创建一个Qt应用程序的实例 */ QGuiApplication app(argc, argv); // 创建Person对象 Person person; QQmlApplicationEngine engine; /* 将Person对象作为QML上下文属性 */ engine.rootContext()->setContextProperty("person", &person); const QUrl url(QStringLiteral("qrc:/main.qml")); /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */ /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加载QML文件并显示用户界面 */ engine.load(url); return app.exec(); }
-
main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") Column { spacing: 10 TextField { placeholderText: "请输入姓名" text: person.name // 与Person对象的name属性绑定 onTextChanged: person.name = text // 当文本改变时,更新Person对象的name属性 } Slider { from: 0 to: 100 value: person.age // 与Person对象的age属性绑定 onValueChanged: person.age = value // 当滑块值改变时,更新Person对象的age属性 } Text { text: "姓名:" + person.name } Text { text: "年龄:" + person.age } } }
二、信号与槽
C++ 对象可以发出信号,而QML中的元素可以连接到这些信号上。这样,当C++ 对象的状态发生变化时,可以通过信号与槽机制将这些变化传递给QML界面。
-
myobject.h
#include #include class MyObject : public QObject { Q_OBJECT public: explicit MyObject(QObject *parent = nullptr) : QObject(parent) {} signals: void mySignal(QString message); public slots: void mySlot(const QString& message) { qDebug()
-
main.cpp
#include #include #include #include "myobject.h" int main(int argc, char *argv[]) { /* 启用Qt应用程序的高DPI缩放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 创建一个Qt应用程序的实例 */ QGuiApplication app(argc, argv); /* 将自定义 C++ 类型注册到 QML 中的函数, 将自定义 C++ 类型注册到 QML 中的函数 */ qmlRegisterType("com.example", 1, 0, "MyObject"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */ /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加载QML文件并显示用户界面 */ engine.load(url); return app.exec(); }
-
main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 import com.example 1.0 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") /* 定义 sendToCpp 信号 */ signal sendToCpp(string message) /* Connections 组件用于连接 myObject 的 onMySignal 信号 */ Connections { targ服务器托管网et: myObject onMySignal: console.log("Received message from C++:", message) } MyObject { id: myObject /* 将 onMySignal 信号传递到 sendToCpp信号上,便于 QML 处理 */ onMySignal: sendToCpp(message) } Button { text: "Send message to C++" anchors.centerIn: parent /* 单击按钮时,会将信号传递到 C++ 的 mySlot 槽上 */ onClicked: myObject.mySlot("Hello from QML") } }
三、模型视图
模型视图(Model-View):可以使用C++ 中的数据模型(QStandardItemModel)来提供数据给QML界面。QML中的视图元素(如ListView或GridView)可以使用这些模型来显示数据。
-
mymodel.h
#ifndef MYMODEL_H #define MYMODEL_H #include #include class MyModel : public QAbstractListModel { Q_OBJECT public: explicit MyModel(QObject *parent = nullptr); enum { NameRole = Qt::UserRole + 1, AgeRole, EmailRole }; // 重写以下几个虚函数 int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash roleNames() const override; private: struct Person { QString name; int age; QString email; }; QList m_persons; }; #endif // MYMODEL_H
-
mymodel.cpp
#include "mymodel.h" MyModel::MyModel(QObject *parent) : QAbstractListModel(parent) { // 初始化一些数据 m_persons.append({"Alice", 25, "alice@example.com"}); m_persons.append({"Bob", 30, "bob@example.com"}); m_persons.append({"Charlie", 35, "charlie@example.com"}); } int MyModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_persons.count(); } QVariant MyModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= m_persons.count() || index.row() MyModel::roleNames() const { QHash roles; roles[NameRole] = "name"; roles[AgeRole] = "age"; roles[EmailRole] = "email"; return roles; }
-
main服务器托管网.cpp
#include #include #include #include "mymodel.h" int main(int argc, char *argv[]) { /* 启用Qt应用程序的高DPI缩放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 创建一个Qt应用程序的实例 */ QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyModel myModel; engine.rootContext()->setContextProperty("myModel", &myModel); const QUrl url(QStringLiteral("qrc:/main.qml")); /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */ /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加载QML文件并显示用户界面 */ engine.load(url); return app.exec(); }
-
main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") ListView { anchors.fill: parent model: myModel delegate: Item { width: parent.width height: 60 Column { Text { text: name } Text { text: age } Text { text: email } } } } }
-
运行效果
四、QML类型注册
QML类型注册(QML Type Registration):可以将C++ 对象注册为自定义的QML类型,使得QML可以直接创建和使用这些对象。通过在C++ 中使用 Q_PROPERTY 宏和 Q_INVOKABLE 函数,可以将C++ 类注册为QML类型。我需要这样一个案例
-
myobject.h
#include #include "QDebug" class MyObject : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) public: explicit MyObject(QObject *parent = nullptr) : QObject(parent) {} QString name() const { return m_name; } void setName(const QString &name) { m_name = name; emit nameChanged(); } Q_INVOKABLE void printName() { qDebug() ("com.example", 1, 0, "MyObject"); } signals: void nameChanged(); private: QString m_name; };
-
main.cpp
#include #include #include #include "myobject.h" int main(int argc, char *argv[]) { /* 启用Qt应用程序的高DPI缩放功能 */ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); /* 创建一个Qt应用程序的实例 */ QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyObject::registerQmlType(); const QUrl url(QStringLiteral("qrc:/main.qml")); /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */ /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); /* 加载QML文件并显示用户界面 */ engine.load(url); return app.exec(); }
-
main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 import com.example 1.0 Window { visible: true width: 480 height: 800 title: qsTr("Hello World") MyObject { id: myObject name: "John" } /* 垂直布置组件 */ Column { anchors.fill: parent // 大小为父组件的大小 anchors.margins: 40 // 与父组件四周的间隔 spacing: 10 // 子组件之间的间隔 Text { text: myObject.name } Button { text: "Print Name" onClicked: myObject.printName() } } }
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
导言 最近,我看到了这样一个视频,觉得很有意思,就随手保存下来了。😁😁😁 之前吃串串火锅,老板数竹签不是称重就是用手慢慢数,但是称重似乎总是得不到正确的竹签数目,而且容易暗箱操作;而慢慢数总是要等待比较长的时间,感觉两者对处理数竹签的问题都存在比较大的缺陷。因…