目录
1.1 QMetaObject::invokeMethod调用
以前写过一篇C++和QML交互的的文章(C++与QML交互总结_qml和c++交互_hsy12342611的博客-CSDN博客),很多网友都在看并提出了一些疑问,本篇结合网上的资料从另外一个角度再重新梳理一下C++与QML的交互。

main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
- engine.load(url);
-
- //cpp调用qml指定对象的指定方法
- auto rootObj = engine.rootObjects();
- // rootObj.first()获取所有对象列表
- auto label = rootObj.first()->findChild
("qml_label"); -
- // 通过元对象调用
- QVariant ret;
- QMetaObject::invokeMethod(label, "getText",
- Q_RETURN_ARG(QVariant, ret),
- Q_ARG(QVariant, " hello"));
-
- qDebug() << ret.toString();
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Label {
- objectName: "qml_label"
- text: "QML Label"
- font.pixelSize: 25
-
- function getText(data) {
- return text + data
- }
- }
- }
-
- }

main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include
- #include
- #include
- #include "person.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- Person person("张三", 18);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
-
- //上下文: 将类对象注册到QML的上下文背景中
- auto ctext = engine.rootContext();
- ctext->setContextProperty("OtPerson", &person);
-
- // 先在上下文注入,再加载
- engine.load(url);
-
- //cpp获取qml中的指定对象
- auto rootObj = engine.rootObjects();
- // rootObj.first()获取所有对象列表
- auto button = rootObj.first()->findChild
("qml_button"); - // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
- QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
- QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
- /*
- // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
- auto button = rootObj.first()->findChild
("qml_button"); - if (!button) {
- qDebug() << "button is nullptr";
- }
- QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
- */
-
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
- import QtQml 2.15
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: "QML button"
- font.pixelSize: 25
- property int cal: 1
- // qml中自定义信号
- signal coutNum(int num)
-
- onClicked: {
- OtPerson.showInfo()
- if (0 == cal++ % 10) {
- coutNum(cal)
- }
- }
-
- // cpp的信号绑定qml的槽
- Connections {
- target: OtPerson
- function onQmlCall() {
- console.log("cpp call qml")
- }
- }
-
- Connections {
- target: OtPerson
- function onQmlCall(data) {
- console.log("cpp call qml " + data)
- }
- }
- }
- }
-
- }

main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include "person.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- Person person("张三", 18);
- // qml单实例注册
- qmlRegisterSingletonInstance("PersonMudle", 1, 0, "MyPerson", &person);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
- engine.load(url);
-
- return app.exec();
- }
-
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
- import PersonMudle 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: "QML button"
- font.pixelSize: 25
-
- onClicked: {
- MyPerson.showInfo()
- }
- }
- }
-
- }

main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include
- #include "person.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- Person person("张三", 18);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
- engine.load(url);
-
- //上下文: 将类对象注册到QML的上下文背景中
- auto ctext = engine.rootContext();
- ctext->setContextProperty("OtPerson", &person);
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: "QML button"
- font.pixelSize: 25
-
- onClicked: {
- OtPerson.showInfo()
- }
- }
- }
-
- }

main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include
- #include
- #include
- #include "person.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- Person person("张三", 18);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
- engine.load(url);
-
- //上下文: 将类对象注册到QML的上下文背景中
- auto ctext = engine.rootContext();
- ctext->setContextProperty("OtPerson", &person);
-
- //cpp获取qml中的指定对象
- auto rootObj = engine.rootObjects();
- // rootObj.first()获取所有对象列表
- auto button = rootObj.first()->findChild
("qml_button"); - // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
- QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
- QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
- /*
- // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
- auto button = rootObj.first()->findChild
("qml_button"); - if (!button) {
- qDebug() << "button is nullptr";
- }
- QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clieckButton);
- */
-
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: "QML button"
- font.pixelSize: 25
- property int cal: 1
- // qml中自定义信号
- signal coutNum(int num)
-
- onClicked: {
- OtPerson.showInfo()
- if (0 == cal++ % 10) {
- coutNum(cal)
- }
- }
- }
- }
-
- }
main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include
- #include
- #include
- #include "person.h"
- #include "tree.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- // 注册一个C++类型到qml中
- qmlRegisterType
("TreeMudle", 1, 0, "MyTree"); -
- Person person("张三", 18);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
-
- //上下文: 将类对象注册到QML的上下文背景中
- auto ctext = engine.rootContext();
- ctext->setContextProperty("OtPerson", &person);
-
- // 先在上下文注入,再加载
- engine.load(url);
-
- //cpp获取qml中的指定对象
- auto rootObj = engine.rootObjects();
- // rootObj.first()获取所有对象列表
- auto button = rootObj.first()->findChild
("qml_button"); - // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
- QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
- QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
- /*
- // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
- auto button = rootObj.first()->findChild
("qml_button"); - if (!button) {
- qDebug() << "button is nullptr";
- }
- QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
- */
-
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
- import QtQml 2.15
- import TreeMudle 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")
- font.pixelSize: 25
- property int cal: 1
- // qml中自定义信号
- signal coutNum(int num)
-
- onClicked: {
- OtPerson.showInfo()
- if (0 == cal++ % 10) {
- coutNum(cal)
- }
- tree.name = "李四"
- }
-
- // cpp的信号绑定qml的槽
- Connections {
- target: OtPerson
- function onQmlCall() {
- console.log("cpp call qml")
- }
- }
-
- Connections {
- target: OtPerson
- function onQmlCall(data) {
- console.log("cpp call qml " + data)
- }
- }
- }
-
- // 使用cpp注入的类型
- MyTree {
- id: tree
- name: 'My_Tree'
- age: 110
- date: new Date()
-
- onNameChanged: {
- console.log("changed name: " + name)
-
- }
- }
- }
-
- }
.pro
- QT += quick
-
- QT += core gui
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++17 qmltypes
-
- QML_IMPORT_NAME = TreeMudle
- QML_IMPORT_MAJOR_VERSION = 1
-
- # You can make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp \
- person.cpp \
- tree.cpp
-
- RESOURCES += qml.qrc
-
- # Additional import path used to resolve QML modules in Qt Creator's code model
- QML_IMPORT_PATH =
-
- # Additional import path used to resolve QML modules just for Qt Quick Designer
- QML_DESIGNER_IMPORT_PATH =
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
-
- HEADERS += \
- person.h \
- tree.h
main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include
- #include
- #include
- #include "person.h"
- #include "tree.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- Person person("张三", 18);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
-
- //上下文: 将类对象注册到QML的上下文背景中
- auto ctext = engine.rootContext();
- ctext->setContextProperty("OtPerson", &person);
-
- // 先在上下文注入,再加载
- engine.load(url);
-
- //cpp获取qml中的指定对象
- auto rootObj = engine.rootObjects();
- // rootObj.first()获取所有对象列表
- auto button = rootObj.first()->findChild
("qml_button"); - // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
- QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
- QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
- /*
- // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
- auto button = rootObj.first()->findChild
("qml_button"); - if (!button) {
- qDebug() << "button is nullptr";
- }
- QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
- */
-
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
- import QtQml 2.15
- import TreeMudle 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")
- font.pixelSize: 25
- property int cal: 1
- // qml中自定义信号
- signal coutNum(int num)
-
- onClicked: {
- OtPerson.showInfo()
- if (0 == cal++ % 10) {
- coutNum(cal)
- }
- tree.name = "李四"
- }
-
- // cpp的信号绑定qml的槽
- Connections {
- target: OtPerson
- function onQmlCall() {
- console.log("cpp call qml")
- }
- }
-
- Connections {
- target: OtPerson
- function onQmlCall(data) {
- console.log("cpp call qml " + data)
- }
- }
- }
-
- // 使用cpp注入的类型
- Tree {
- id: tree
- name: 'My_Tree'
- age: 110
- date: new Date()
-
- onNameChanged: {
- console.log("changed name: " + name)
-
- }
- }
- }
-
- }
person.h
- #ifndef PERSON_H
- #define PERSON_H
-
- #include
- #include
- #include "tree.h"
-
- class Person : public QObject
- {
- Q_OBJECT
- //类的附加属性
- QML_ATTACHED(Tree)
-
- public:
- explicit Person(QObject *parent = nullptr);
- Person(QString name, int age);
- // 想要让QML调用函数,函数要加上宏Q_INVOKABLE
- Q_INVOKABLE void showInfo() const noexcept;
-
- public slots:
- void clickButton() const noexcept;
- void clickCal(int data) const noexcept;
-
- signals:
- void qmlCall() const;
- // cpp给qml传参数不是所有类型都可以,一般就字符串,json和基本类型可以
- void qmlCall(QString) const;
-
- private:
- QString _name;
- int _age;
-
- };
-
- #endif // PERSON_H
person.cpp
- #include "person.h"
- #include
-
- Person::Person(QObject *parent)
- : QObject{parent}
- {
-
- }
-
- Person::Person(QString name, int age) {
- _name = name;
- _age = age;
- }
-
- void Person::showInfo() const noexcept {
- qDebug() << "name: " << _name << ", age: "<< _age;
-
- // cpp发送信号调用qml中的槽
- emit qmlCall();
- emit qmlCall("王五");
- }
-
- void Person::clickButton() const noexcept {
- qDebug() << __FUNCTION__ << " in qml: click button";
- }
-
- void Person::clickCal(int data) const noexcept {
- qDebug() << __FUNCTION__ << " " << data;
- }
tree.h
- #ifndef TREE_H
- #define TREE_H
-
- #include
- #include
- #include
-
- //使用QML_ELEMENT后,就会产生元数据类型:描述数据的数据
-
- class Tree : public QObject
- {
- Q_OBJECT
- // qml中使用cpp类的属性
- Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
- Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY dateChanged)
-
- QML_ELEMENT
-
- public:
- explicit Tree(QObject *parent = nullptr);
- Tree(QString nme, qint32 age, QDate date);
-
- void setName(QString name) noexcept;
- void setAge(qint32 age) noexcept;
- void setDate(QDate date) noexcept;
-
- QString getName() const noexcept;
- qint32 getAge() const noexcept;
- QDate getDate() const noexcept;
-
- signals:
- void nameChanged(QString);
- void ageChanged();
- void dateChanged();
-
- private:
- QString _name;
- qint32 _age;
- QDate _date;
- };
-
- #endif // TREE_H
tree.cpp
- #include "tree.h"
-
- Tree::Tree(QObject *parent)
- : QObject{parent}
- {
-
- }
-
- Tree::Tree(QString name, qint32 age, QDate date) {
- _name = name;
- _age = age;
- _date = date;
- }
-
- void Tree::setName(QString name) noexcept {
- _name = name;
- emit nameChanged(name);
- }
-
- void Tree::setAge(qint32 age) noexcept {
- _age = age;
- emit ageChanged();
- }
-
- void Tree::setDate(QDate date) noexcept {
- _date = date;
- emit dateChanged();
- }
-
- QString Tree::getName() const noexcept {
- return _name;
- }
-
- qint32 Tree::getAge() const noexcept {
- return _age;
- }
-
- QDate Tree::getDate() const noexcept {
- return _date;
- }
-
使用附加属性:本质上会创建一个附加属性对象
效果如下:

tree.h
- #ifndef TREE_H
- #define TREE_H
-
- #include
- #include
- #include
-
- //使用QML_ELEMENT后,就会产生元数据类型:描述数据的数据
-
- class Tree : public QObject
- {
- Q_OBJECT
- // qml中使用cpp类的属性
- Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
- Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY dateChanged)
-
- QML_ANONYMOUS
-
- public:
- explicit Tree(QObject *parent = nullptr);
- Tree(QString nme, qint32 age, QDate date);
-
- void setName(QString name) noexcept;
- void setAge(qint32 age) noexcept;
- void setDate(QDate date) noexcept;
-
- QString getName() const noexcept;
- qint32 getAge() const noexcept;
- QDate getDate() const noexcept;
-
- signals:
- void nameChanged(QString);
- void ageChanged();
- void dateChanged();
-
- private:
- QString _name;
- qint32 _age;
- QDate _date;
- };
-
- #endif // TREE_H
tree.cpp
- #include "tree.h"
-
- Tree::Tree(QObject *parent)
- : QObject{parent}
- {
-
- }
-
- Tree::Tree(QString name, qint32 age, QDate date) {
- _name = name;
- _age = age;
- _date = date;
- }
-
- void Tree::setName(QString name) noexcept {
- _name = name;
- emit nameChanged(name);
- }
-
- void Tree::setAge(qint32 age) noexcept {
- _age = age;
- emit ageChanged();
- }
-
- void Tree::setDate(QDate date) noexcept {
- _date = date;
- emit dateChanged();
- }
-
- QString Tree::getName() const noexcept {
- return _name;
- }
-
- qint32 Tree::getAge() const noexcept {
- return _age;
- }
-
- QDate Tree::getDate() const noexcept {
- return _date;
- }
-
person.h
- #ifndef PERSON_H
- #define PERSON_H
-
- #include
- #include
- #include "tree.h"
-
- class Person : public QObject
- {
- Q_OBJECT
- //类的附加属性,将Tree中的属性附加到Person类中
- QML_ATTACHED(Tree)
- QML_ELEMENT
-
- public:
- explicit Person(QObject *parent = nullptr);
- Person(QString name, int age);
- // 想要让QML调用函数,函数要加上宏Q_INVOKABLE
- Q_INVOKABLE void showInfo() const noexcept;
-
- public slots:
- void clickButton() const noexcept;
- void clickCal(int data) const noexcept;
-
- static Tree* qmlAttachedProperties(QObject*);
-
- signals:
- void qmlCall() const;
- // cpp给qml传参数不是所有类型都可以,一般就字符串,json和基本类型可以
- void qmlCall(QString) const;
-
- private:
- QString _name;
- int _age;
-
- };
-
- #endif // PERSON_H
person.cpp
- #include "person.h"
- #include
-
- Person::Person(QObject *parent)
- : QObject{parent}
- {
-
- }
-
- Person::Person(QString name, int age) {
- _name = name;
- _age = age;
- }
-
- void Person::showInfo() const noexcept {
- qDebug() << "name: " << _name << ", age: "<< _age;
-
- // cpp发送信号调用qml中的槽
- emit qmlCall();
- emit qmlCall("王五");
- }
-
- void Person::clickButton() const noexcept {
- qDebug() << __FUNCTION__ << " in qml: click button";
- }
-
- void Person::clickCal(int data) const noexcept {
- qDebug() << __FUNCTION__ << " " << data;
- }
-
- Tree* Person::qmlAttachedProperties(QObject* obj) {
- qDebug() << __FUNCTION__ << obj;
- return new Tree(obj);
- }
main.cpp
- #include
- #include
- // 元对象头文件
- #include
- #include
- #include
- #include
- #include
- #include "person.h"
- #include "tree.h"
-
-
- int main(int argc, char *argv[])
- {
- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- #endif
- QGuiApplication app(argc, argv);
-
- Person person("张三", 18);
-
- QQmlApplicationEngine engine;
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
- &app, [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- }, Qt::QueuedConnection);
-
- //上下文: 将类对象注册到QML的上下文背景中
- auto ctext = engine.rootContext();
- ctext->setContextProperty("OtPerson", &person);
-
- // 先在上下文注入,再加载
- engine.load(url);
-
- //cpp获取qml中的指定对象
- auto rootObj = engine.rootObjects();
- // rootObj.first()获取所有对象列表
- auto button = rootObj.first()->findChild
("qml_button"); - // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
- QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
- QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
- /*
- // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
- auto button = rootObj.first()->findChild
("qml_button"); - if (!button) {
- qDebug() << "button is nullptr";
- }
- QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
- */
-
-
- return app.exec();
- }
main.qml
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import QtQuick.Controls 2.15 as QtCtrl
- import QtQuick.Layouts 1.0
- import QtQml 2.15
- import PersonMudle 1.0
-
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("qml和cpp交互总结")
-
- Item {
- id: item
- anchors.fill: parent
-
- QtCtrl.Button {
- objectName: "qml_button"
- text: Person.name + Person.age + Person.date
- font.pixelSize: 25
- property int cal: 1
- // qml中自定义信号
- signal coutNum(int num)
-
- onClicked: {
- OtPerson.showInfo()
- if (0 == cal++ % 10) {
- coutNum(cal)
- }
- console.log(Person.name + " " + Person.age + " " + Person.date)
- console.log(this)
- }
-
- // cpp的信号绑定qml的槽
- Connections {
- target: OtPerson
- function onQmlCall() {
- console.log("cpp call qml")
- }
- }
-
- Connections {
- target: OtPerson
- function onQmlCall(data) {
- console.log("cpp call qml " + data)
- }
- }
-
- // 使用附加属性:本质上会创建一个附加属性对象
- Person.name: "赵六"
- Person.age: 25
- Person.date: new Date()
- }
- }
-
- }
.pro
- QT += quick
-
- QT += core gui
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++17 qmltypes
-
- QML_IMPORT_NAME = PersonMudle
- QML_IMPORT_MAJOR_VERSION = 1
-
- # You can make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp \
- person.cpp \
- tree.cpp
-
- RESOURCES += qml.qrc
-
- # Additional import path used to resolve QML modules in Qt Creator's code model
- QML_IMPORT_PATH =
-
- # Additional import path used to resolve QML modules just for Qt Quick Designer
- QML_DESIGNER_IMPORT_PATH =
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
-
- HEADERS += \
- person.h \
- tree.h