• C++与QML交互总结二


    目录

    1.CPP调用QML

    1.1 QMetaObject::invokeMethod调用

    1.2 CPP中的信号绑定qml中的槽

    2.QML调用CPP

    2.1 QML单实例注册

    2.2 将类对象注册到QML的上下文中

    2.3 QML信号调用CPP槽

    3.QML中注入一个cpp实例

    3.1qmlRegisterType

    3.2QML_ELEMENT

    4.附加属性: QML_ATTACHED


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

    1.CPP调用QML

    1.1 QMetaObject::invokeMethod调用

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. int main(int argc, char *argv[])
    7. {
    8. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    9. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    10. #endif
    11. QGuiApplication app(argc, argv);
    12. QQmlApplicationEngine engine;
    13. const QUrl url(QStringLiteral("qrc:/main.qml"));
    14. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    15. &app, [url](QObject *obj, const QUrl &objUrl) {
    16. if (!obj && url == objUrl)
    17. QCoreApplication::exit(-1);
    18. }, Qt::QueuedConnection);
    19. engine.load(url);
    20. //cpp调用qml指定对象的指定方法
    21. auto rootObj = engine.rootObjects();
    22. // rootObj.first()获取所有对象列表
    23. auto label = rootObj.first()->findChild("qml_label");
    24. // 通过元对象调用
    25. QVariant ret;
    26. QMetaObject::invokeMethod(label, "getText",
    27. Q_RETURN_ARG(QVariant, ret),
    28. Q_ARG(QVariant, " hello"));
    29. qDebug() << ret.toString();
    30. return app.exec();
    31. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. Window {
    6. width: 640
    7. height: 480
    8. visible: true
    9. title: qsTr("qml和cpp交互总结")
    10. Item {
    11. id: item
    12. anchors.fill: parent
    13. QtCtrl.Label {
    14. objectName: "qml_label"
    15. text: "QML Label"
    16. font.pixelSize: 25
    17. function getText(data) {
    18. return text + data
    19. }
    20. }
    21. }
    22. }

    1.2 CPP中的信号绑定qml中的槽

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "person.h"
    10. int main(int argc, char *argv[])
    11. {
    12. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    13. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    14. #endif
    15. QGuiApplication app(argc, argv);
    16. Person person("张三", 18);
    17. QQmlApplicationEngine engine;
    18. const QUrl url(QStringLiteral("qrc:/main.qml"));
    19. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    20. &app, [url](QObject *obj, const QUrl &objUrl) {
    21. if (!obj && url == objUrl)
    22. QCoreApplication::exit(-1);
    23. }, Qt::QueuedConnection);
    24. //上下文: 将类对象注册到QML的上下文背景中
    25. auto ctext = engine.rootContext();
    26. ctext->setContextProperty("OtPerson", &person);
    27. // 先在上下文注入,再加载
    28. engine.load(url);
    29. //cpp获取qml中的指定对象
    30. auto rootObj = engine.rootObjects();
    31. // rootObj.first()获取所有对象列表
    32. auto button = rootObj.first()->findChild("qml_button");
    33. // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    34. QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    35. QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    36. /*
    37. // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    38. auto button = rootObj.first()->findChild("qml_button");
    39. if (!button) {
    40. qDebug() << "button is nullptr";
    41. }
    42. QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    43. */
    44. return app.exec();
    45. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. import QtQml 2.15
    6. Window {
    7. width: 640
    8. height: 480
    9. visible: true
    10. title: qsTr("qml和cpp交互总结")
    11. Item {
    12. id: item
    13. anchors.fill: parent
    14. QtCtrl.Button {
    15. objectName: "qml_button"
    16. text: "QML button"
    17. font.pixelSize: 25
    18. property int cal: 1
    19. // qml中自定义信号
    20. signal coutNum(int num)
    21. onClicked: {
    22. OtPerson.showInfo()
    23. if (0 == cal++ % 10) {
    24. coutNum(cal)
    25. }
    26. }
    27. // cpp的信号绑定qml的槽
    28. Connections {
    29. target: OtPerson
    30. function onQmlCall() {
    31. console.log("cpp call qml")
    32. }
    33. }
    34. Connections {
    35. target: OtPerson
    36. function onQmlCall(data) {
    37. console.log("cpp call qml " + data)
    38. }
    39. }
    40. }
    41. }
    42. }

    2.QML调用CPP

    2.1 QML单实例注册

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include "person.h"
    7. int main(int argc, char *argv[])
    8. {
    9. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    10. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    11. #endif
    12. QGuiApplication app(argc, argv);
    13. Person person("张三", 18);
    14. // qml单实例注册
    15. qmlRegisterSingletonInstance("PersonMudle", 1, 0, "MyPerson", &person);
    16. QQmlApplicationEngine engine;
    17. const QUrl url(QStringLiteral("qrc:/main.qml"));
    18. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    19. &app, [url](QObject *obj, const QUrl &objUrl) {
    20. if (!obj && url == objUrl)
    21. QCoreApplication::exit(-1);
    22. }, Qt::QueuedConnection);
    23. engine.load(url);
    24. return app.exec();
    25. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. import PersonMudle 1.0
    6. Window {
    7. width: 640
    8. height: 480
    9. visible: true
    10. title: qsTr("qml和cpp交互总结")
    11. Item {
    12. id: item
    13. anchors.fill: parent
    14. QtCtrl.Button {
    15. objectName: "qml_button"
    16. text: "QML button"
    17. font.pixelSize: 25
    18. onClicked: {
    19. MyPerson.showInfo()
    20. }
    21. }
    22. }
    23. }

    2.2 将类对象注册到QML的上下文中

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include
    7. #include "person.h"
    8. int main(int argc, char *argv[])
    9. {
    10. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    11. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    12. #endif
    13. QGuiApplication app(argc, argv);
    14. Person person("张三", 18);
    15. QQmlApplicationEngine engine;
    16. const QUrl url(QStringLiteral("qrc:/main.qml"));
    17. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    18. &app, [url](QObject *obj, const QUrl &objUrl) {
    19. if (!obj && url == objUrl)
    20. QCoreApplication::exit(-1);
    21. }, Qt::QueuedConnection);
    22. engine.load(url);
    23. //上下文: 将类对象注册到QML的上下文背景中
    24. auto ctext = engine.rootContext();
    25. ctext->setContextProperty("OtPerson", &person);
    26. return app.exec();
    27. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. Window {
    6. width: 640
    7. height: 480
    8. visible: true
    9. title: qsTr("qml和cpp交互总结")
    10. Item {
    11. id: item
    12. anchors.fill: parent
    13. QtCtrl.Button {
    14. objectName: "qml_button"
    15. text: "QML button"
    16. font.pixelSize: 25
    17. onClicked: {
    18. OtPerson.showInfo()
    19. }
    20. }
    21. }
    22. }

    2.3 QML信号调用CPP槽

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "person.h"
    10. int main(int argc, char *argv[])
    11. {
    12. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    13. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    14. #endif
    15. QGuiApplication app(argc, argv);
    16. Person person("张三", 18);
    17. QQmlApplicationEngine engine;
    18. const QUrl url(QStringLiteral("qrc:/main.qml"));
    19. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    20. &app, [url](QObject *obj, const QUrl &objUrl) {
    21. if (!obj && url == objUrl)
    22. QCoreApplication::exit(-1);
    23. }, Qt::QueuedConnection);
    24. engine.load(url);
    25. //上下文: 将类对象注册到QML的上下文背景中
    26. auto ctext = engine.rootContext();
    27. ctext->setContextProperty("OtPerson", &person);
    28. //cpp获取qml中的指定对象
    29. auto rootObj = engine.rootObjects();
    30. // rootObj.first()获取所有对象列表
    31. auto button = rootObj.first()->findChild("qml_button");
    32. // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    33. QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    34. QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    35. /*
    36. // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    37. auto button = rootObj.first()->findChild("qml_button");
    38. if (!button) {
    39. qDebug() << "button is nullptr";
    40. }
    41. QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clieckButton);
    42. */
    43. return app.exec();
    44. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. Window {
    6. width: 640
    7. height: 480
    8. visible: true
    9. title: qsTr("qml和cpp交互总结")
    10. Item {
    11. id: item
    12. anchors.fill: parent
    13. QtCtrl.Button {
    14. objectName: "qml_button"
    15. text: "QML button"
    16. font.pixelSize: 25
    17. property int cal: 1
    18. // qml中自定义信号
    19. signal coutNum(int num)
    20. onClicked: {
    21. OtPerson.showInfo()
    22. if (0 == cal++ % 10) {
    23. coutNum(cal)
    24. }
    25. }
    26. }
    27. }
    28. }

    3.QML中注入一个cpp实例

    3.1qmlRegisterType

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "person.h"
    10. #include "tree.h"
    11. int main(int argc, char *argv[])
    12. {
    13. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    14. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    15. #endif
    16. QGuiApplication app(argc, argv);
    17. // 注册一个C++类型到qml中
    18. qmlRegisterType("TreeMudle", 1, 0, "MyTree");
    19. Person person("张三", 18);
    20. QQmlApplicationEngine engine;
    21. const QUrl url(QStringLiteral("qrc:/main.qml"));
    22. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    23. &app, [url](QObject *obj, const QUrl &objUrl) {
    24. if (!obj && url == objUrl)
    25. QCoreApplication::exit(-1);
    26. }, Qt::QueuedConnection);
    27. //上下文: 将类对象注册到QML的上下文背景中
    28. auto ctext = engine.rootContext();
    29. ctext->setContextProperty("OtPerson", &person);
    30. // 先在上下文注入,再加载
    31. engine.load(url);
    32. //cpp获取qml中的指定对象
    33. auto rootObj = engine.rootObjects();
    34. // rootObj.first()获取所有对象列表
    35. auto button = rootObj.first()->findChild("qml_button");
    36. // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    37. QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    38. QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    39. /*
    40. // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    41. auto button = rootObj.first()->findChild("qml_button");
    42. if (!button) {
    43. qDebug() << "button is nullptr";
    44. }
    45. QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    46. */
    47. return app.exec();
    48. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. import QtQml 2.15
    6. import TreeMudle 1.0
    7. Window {
    8. width: 640
    9. height: 480
    10. visible: true
    11. title: qsTr("qml和cpp交互总结")
    12. Item {
    13. id: item
    14. anchors.fill: parent
    15. QtCtrl.Button {
    16. objectName: "qml_button"
    17. text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")
    18. font.pixelSize: 25
    19. property int cal: 1
    20. // qml中自定义信号
    21. signal coutNum(int num)
    22. onClicked: {
    23. OtPerson.showInfo()
    24. if (0 == cal++ % 10) {
    25. coutNum(cal)
    26. }
    27. tree.name = "李四"
    28. }
    29. // cpp的信号绑定qml的槽
    30. Connections {
    31. target: OtPerson
    32. function onQmlCall() {
    33. console.log("cpp call qml")
    34. }
    35. }
    36. Connections {
    37. target: OtPerson
    38. function onQmlCall(data) {
    39. console.log("cpp call qml " + data)
    40. }
    41. }
    42. }
    43. // 使用cpp注入的类型
    44. MyTree {
    45. id: tree
    46. name: 'My_Tree'
    47. age: 110
    48. date: new Date()
    49. onNameChanged: {
    50. console.log("changed name: " + name)
    51. }
    52. }
    53. }
    54. }

    3.2QML_ELEMENT

    .pro

    1. QT += quick
    2. QT += core gui
    3. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    4. CONFIG += c++17 qmltypes
    5. QML_IMPORT_NAME = TreeMudle
    6. QML_IMPORT_MAJOR_VERSION = 1
    7. # You can make your code fail to compile if it uses deprecated APIs.
    8. # In order to do so, uncomment the following line.
    9. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    10. SOURCES += \
    11. main.cpp \
    12. person.cpp \
    13. tree.cpp
    14. RESOURCES += qml.qrc
    15. # Additional import path used to resolve QML modules in Qt Creator's code model
    16. QML_IMPORT_PATH =
    17. # Additional import path used to resolve QML modules just for Qt Quick Designer
    18. QML_DESIGNER_IMPORT_PATH =
    19. # Default rules for deployment.
    20. qnx: target.path = /tmp/$${TARGET}/bin
    21. else: unix:!android: target.path = /opt/$${TARGET}/bin
    22. !isEmpty(target.path): INSTALLS += target
    23. HEADERS += \
    24. person.h \
    25. tree.h

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "person.h"
    10. #include "tree.h"
    11. int main(int argc, char *argv[])
    12. {
    13. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    14. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    15. #endif
    16. QGuiApplication app(argc, argv);
    17. Person person("张三", 18);
    18. QQmlApplicationEngine engine;
    19. const QUrl url(QStringLiteral("qrc:/main.qml"));
    20. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    21. &app, [url](QObject *obj, const QUrl &objUrl) {
    22. if (!obj && url == objUrl)
    23. QCoreApplication::exit(-1);
    24. }, Qt::QueuedConnection);
    25. //上下文: 将类对象注册到QML的上下文背景中
    26. auto ctext = engine.rootContext();
    27. ctext->setContextProperty("OtPerson", &person);
    28. // 先在上下文注入,再加载
    29. engine.load(url);
    30. //cpp获取qml中的指定对象
    31. auto rootObj = engine.rootObjects();
    32. // rootObj.first()获取所有对象列表
    33. auto button = rootObj.first()->findChild("qml_button");
    34. // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    35. QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    36. QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    37. /*
    38. // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    39. auto button = rootObj.first()->findChild("qml_button");
    40. if (!button) {
    41. qDebug() << "button is nullptr";
    42. }
    43. QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    44. */
    45. return app.exec();
    46. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. import QtQml 2.15
    6. import TreeMudle 1.0
    7. Window {
    8. width: 640
    9. height: 480
    10. visible: true
    11. title: qsTr("qml和cpp交互总结")
    12. Item {
    13. id: item
    14. anchors.fill: parent
    15. QtCtrl.Button {
    16. objectName: "qml_button"
    17. text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")
    18. font.pixelSize: 25
    19. property int cal: 1
    20. // qml中自定义信号
    21. signal coutNum(int num)
    22. onClicked: {
    23. OtPerson.showInfo()
    24. if (0 == cal++ % 10) {
    25. coutNum(cal)
    26. }
    27. tree.name = "李四"
    28. }
    29. // cpp的信号绑定qml的槽
    30. Connections {
    31. target: OtPerson
    32. function onQmlCall() {
    33. console.log("cpp call qml")
    34. }
    35. }
    36. Connections {
    37. target: OtPerson
    38. function onQmlCall(data) {
    39. console.log("cpp call qml " + data)
    40. }
    41. }
    42. }
    43. // 使用cpp注入的类型
    44. Tree {
    45. id: tree
    46. name: 'My_Tree'
    47. age: 110
    48. date: new Date()
    49. onNameChanged: {
    50. console.log("changed name: " + name)
    51. }
    52. }
    53. }
    54. }

    person.h

    1. #ifndef PERSON_H
    2. #define PERSON_H
    3. #include
    4. #include
    5. #include "tree.h"
    6. class Person : public QObject
    7. {
    8. Q_OBJECT
    9. //类的附加属性
    10. QML_ATTACHED(Tree)
    11. public:
    12. explicit Person(QObject *parent = nullptr);
    13. Person(QString name, int age);
    14. // 想要让QML调用函数,函数要加上宏Q_INVOKABLE
    15. Q_INVOKABLE void showInfo() const noexcept;
    16. public slots:
    17. void clickButton() const noexcept;
    18. void clickCal(int data) const noexcept;
    19. signals:
    20. void qmlCall() const;
    21. // cpp给qml传参数不是所有类型都可以,一般就字符串,json和基本类型可以
    22. void qmlCall(QString) const;
    23. private:
    24. QString _name;
    25. int _age;
    26. };
    27. #endif // PERSON_H

    person.cpp

    1. #include "person.h"
    2. #include
    3. Person::Person(QObject *parent)
    4. : QObject{parent}
    5. {
    6. }
    7. Person::Person(QString name, int age) {
    8. _name = name;
    9. _age = age;
    10. }
    11. void Person::showInfo() const noexcept {
    12. qDebug() << "name: " << _name << ", age: "<< _age;
    13. // cpp发送信号调用qml中的槽
    14. emit qmlCall();
    15. emit qmlCall("王五");
    16. }
    17. void Person::clickButton() const noexcept {
    18. qDebug() << __FUNCTION__ << " in qml: click button";
    19. }
    20. void Person::clickCal(int data) const noexcept {
    21. qDebug() << __FUNCTION__ << " " << data;
    22. }

    tree.h

    1. #ifndef TREE_H
    2. #define TREE_H
    3. #include
    4. #include
    5. #include
    6. //使用QML_ELEMENT后,就会产生元数据类型:描述数据的数据
    7. class Tree : public QObject
    8. {
    9. Q_OBJECT
    10. // qml中使用cpp类的属性
    11. Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    12. Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
    13. Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY dateChanged)
    14. QML_ELEMENT
    15. public:
    16. explicit Tree(QObject *parent = nullptr);
    17. Tree(QString nme, qint32 age, QDate date);
    18. void setName(QString name) noexcept;
    19. void setAge(qint32 age) noexcept;
    20. void setDate(QDate date) noexcept;
    21. QString getName() const noexcept;
    22. qint32 getAge() const noexcept;
    23. QDate getDate() const noexcept;
    24. signals:
    25. void nameChanged(QString);
    26. void ageChanged();
    27. void dateChanged();
    28. private:
    29. QString _name;
    30. qint32 _age;
    31. QDate _date;
    32. };
    33. #endif // TREE_H

    tree.cpp

    1. #include "tree.h"
    2. Tree::Tree(QObject *parent)
    3. : QObject{parent}
    4. {
    5. }
    6. Tree::Tree(QString name, qint32 age, QDate date) {
    7. _name = name;
    8. _age = age;
    9. _date = date;
    10. }
    11. void Tree::setName(QString name) noexcept {
    12. _name = name;
    13. emit nameChanged(name);
    14. }
    15. void Tree::setAge(qint32 age) noexcept {
    16. _age = age;
    17. emit ageChanged();
    18. }
    19. void Tree::setDate(QDate date) noexcept {
    20. _date = date;
    21. emit dateChanged();
    22. }
    23. QString Tree::getName() const noexcept {
    24. return _name;
    25. }
    26. qint32 Tree::getAge() const noexcept {
    27. return _age;
    28. }
    29. QDate Tree::getDate() const noexcept {
    30. return _date;
    31. }

    4.附加属性: QML_ATTACHED

    使用附加属性:本质上会创建一个附加属性对象

    效果如下:

    tree.h

    1. #ifndef TREE_H
    2. #define TREE_H
    3. #include
    4. #include
    5. #include
    6. //使用QML_ELEMENT后,就会产生元数据类型:描述数据的数据
    7. class Tree : public QObject
    8. {
    9. Q_OBJECT
    10. // qml中使用cpp类的属性
    11. Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    12. Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
    13. Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY dateChanged)
    14. QML_ANONYMOUS
    15. public:
    16. explicit Tree(QObject *parent = nullptr);
    17. Tree(QString nme, qint32 age, QDate date);
    18. void setName(QString name) noexcept;
    19. void setAge(qint32 age) noexcept;
    20. void setDate(QDate date) noexcept;
    21. QString getName() const noexcept;
    22. qint32 getAge() const noexcept;
    23. QDate getDate() const noexcept;
    24. signals:
    25. void nameChanged(QString);
    26. void ageChanged();
    27. void dateChanged();
    28. private:
    29. QString _name;
    30. qint32 _age;
    31. QDate _date;
    32. };
    33. #endif // TREE_H

    tree.cpp

    1. #include "tree.h"
    2. Tree::Tree(QObject *parent)
    3. : QObject{parent}
    4. {
    5. }
    6. Tree::Tree(QString name, qint32 age, QDate date) {
    7. _name = name;
    8. _age = age;
    9. _date = date;
    10. }
    11. void Tree::setName(QString name) noexcept {
    12. _name = name;
    13. emit nameChanged(name);
    14. }
    15. void Tree::setAge(qint32 age) noexcept {
    16. _age = age;
    17. emit ageChanged();
    18. }
    19. void Tree::setDate(QDate date) noexcept {
    20. _date = date;
    21. emit dateChanged();
    22. }
    23. QString Tree::getName() const noexcept {
    24. return _name;
    25. }
    26. qint32 Tree::getAge() const noexcept {
    27. return _age;
    28. }
    29. QDate Tree::getDate() const noexcept {
    30. return _date;
    31. }

    person.h

    1. #ifndef PERSON_H
    2. #define PERSON_H
    3. #include
    4. #include
    5. #include "tree.h"
    6. class Person : public QObject
    7. {
    8. Q_OBJECT
    9. //类的附加属性,将Tree中的属性附加到Person类中
    10. QML_ATTACHED(Tree)
    11. QML_ELEMENT
    12. public:
    13. explicit Person(QObject *parent = nullptr);
    14. Person(QString name, int age);
    15. // 想要让QML调用函数,函数要加上宏Q_INVOKABLE
    16. Q_INVOKABLE void showInfo() const noexcept;
    17. public slots:
    18. void clickButton() const noexcept;
    19. void clickCal(int data) const noexcept;
    20. static Tree* qmlAttachedProperties(QObject*);
    21. signals:
    22. void qmlCall() const;
    23. // cpp给qml传参数不是所有类型都可以,一般就字符串,json和基本类型可以
    24. void qmlCall(QString) const;
    25. private:
    26. QString _name;
    27. int _age;
    28. };
    29. #endif // PERSON_H

    person.cpp

    1. #include "person.h"
    2. #include
    3. Person::Person(QObject *parent)
    4. : QObject{parent}
    5. {
    6. }
    7. Person::Person(QString name, int age) {
    8. _name = name;
    9. _age = age;
    10. }
    11. void Person::showInfo() const noexcept {
    12. qDebug() << "name: " << _name << ", age: "<< _age;
    13. // cpp发送信号调用qml中的槽
    14. emit qmlCall();
    15. emit qmlCall("王五");
    16. }
    17. void Person::clickButton() const noexcept {
    18. qDebug() << __FUNCTION__ << " in qml: click button";
    19. }
    20. void Person::clickCal(int data) const noexcept {
    21. qDebug() << __FUNCTION__ << " " << data;
    22. }
    23. Tree* Person::qmlAttachedProperties(QObject* obj) {
    24. qDebug() << __FUNCTION__ << obj;
    25. return new Tree(obj);
    26. }

    main.cpp

    1. #include
    2. #include
    3. // 元对象头文件
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "person.h"
    10. #include "tree.h"
    11. int main(int argc, char *argv[])
    12. {
    13. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    14. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    15. #endif
    16. QGuiApplication app(argc, argv);
    17. Person person("张三", 18);
    18. QQmlApplicationEngine engine;
    19. const QUrl url(QStringLiteral("qrc:/main.qml"));
    20. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    21. &app, [url](QObject *obj, const QUrl &objUrl) {
    22. if (!obj && url == objUrl)
    23. QCoreApplication::exit(-1);
    24. }, Qt::QueuedConnection);
    25. //上下文: 将类对象注册到QML的上下文背景中
    26. auto ctext = engine.rootContext();
    27. ctext->setContextProperty("OtPerson", &person);
    28. // 先在上下文注入,再加载
    29. engine.load(url);
    30. //cpp获取qml中的指定对象
    31. auto rootObj = engine.rootObjects();
    32. // rootObj.first()获取所有对象列表
    33. auto button = rootObj.first()->findChild("qml_button");
    34. // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    35. QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    36. QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    37. /*
    38. // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    39. auto button = rootObj.first()->findChild("qml_button");
    40. if (!button) {
    41. qDebug() << "button is nullptr";
    42. }
    43. QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    44. */
    45. return app.exec();
    46. }

    main.qml

    1. import QtQuick 2.15
    2. import QtQuick.Window 2.15
    3. import QtQuick.Controls 2.15 as QtCtrl
    4. import QtQuick.Layouts 1.0
    5. import QtQml 2.15
    6. import PersonMudle 1.0
    7. Window {
    8. width: 640
    9. height: 480
    10. visible: true
    11. title: qsTr("qml和cpp交互总结")
    12. Item {
    13. id: item
    14. anchors.fill: parent
    15. QtCtrl.Button {
    16. objectName: "qml_button"
    17. text: Person.name + Person.age + Person.date
    18. font.pixelSize: 25
    19. property int cal: 1
    20. // qml中自定义信号
    21. signal coutNum(int num)
    22. onClicked: {
    23. OtPerson.showInfo()
    24. if (0 == cal++ % 10) {
    25. coutNum(cal)
    26. }
    27. console.log(Person.name + " " + Person.age + " " + Person.date)
    28. console.log(this)
    29. }
    30. // cpp的信号绑定qml的槽
    31. Connections {
    32. target: OtPerson
    33. function onQmlCall() {
    34. console.log("cpp call qml")
    35. }
    36. }
    37. Connections {
    38. target: OtPerson
    39. function onQmlCall(data) {
    40. console.log("cpp call qml " + data)
    41. }
    42. }
    43. // 使用附加属性:本质上会创建一个附加属性对象
    44. Person.name: "赵六"
    45. Person.age: 25
    46. Person.date: new Date()
    47. }
    48. }
    49. }

    .pro

    1. QT += quick
    2. QT += core gui
    3. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    4. CONFIG += c++17 qmltypes
    5. QML_IMPORT_NAME = PersonMudle
    6. QML_IMPORT_MAJOR_VERSION = 1
    7. # You can make your code fail to compile if it uses deprecated APIs.
    8. # In order to do so, uncomment the following line.
    9. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    10. SOURCES += \
    11. main.cpp \
    12. person.cpp \
    13. tree.cpp
    14. RESOURCES += qml.qrc
    15. # Additional import path used to resolve QML modules in Qt Creator's code model
    16. QML_IMPORT_PATH =
    17. # Additional import path used to resolve QML modules just for Qt Quick Designer
    18. QML_DESIGNER_IMPORT_PATH =
    19. # Default rules for deployment.
    20. qnx: target.path = /tmp/$${TARGET}/bin
    21. else: unix:!android: target.path = /opt/$${TARGET}/bin
    22. !isEmpty(target.path): INSTALLS += target
    23. HEADERS += \
    24. person.h \
    25. tree.h

  • 相关阅读:
    Spring面试题14:Spring中什么是Spring Beans? 包含哪些?Spring容器提供几种方式配置元数据?Spring中怎样定义类的作用域?
    JavaScrip笔记(1)
    【2022 MS MARCO】【阿里】HLATR:基于混合列表感知Transformer重排的多阶段文本检索增强 ( .feat PRM:个性化的推荐重排)
    数据库系统及应用复习——第二章关系数据库
    Redis三种模式——主从复制,哨兵模式,集群
    《梦醒蝶飞:释放Excel函数与公式的力量》1.1.8认识 excel后台视图
    Java核心编程(18)
    Java_FileIO流
    [软件工具][原创]yolov7快速训练助手使用教程傻瓜式训练不需要写代码配置参数
    代码随想录刷题】Day17 二叉树04
  • 原文地址:https://blog.csdn.net/hsy12342611/article/details/133309866