QT之QML从入门到醒目(第七章)

打印 上一主题 下一主题

主题 1781|帖子 1781|积分 5343

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
QML与C++交互

使用全局对象

main.cpp

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQmlContext>
  4. #include <QScreen>
  5. #include <QRect>
  6. int main(int argc, char *argv[])
  7. {
  8.     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  9.     QGuiApplication app(argc, argv);
  10.     QQmlApplicationEngine engine;
  11.     //全局对象,上下文对象
  12.     QQmlContext* context = engine.rootContext();
  13.     QScreen*screen =  QGuiApplication::primaryScreen();
  14.     QRect rect = screen->availableGeometry();
  15.     context->setProperty("SCREEN_WIDTH",rect.width()/2 ); // 定义一个全局的属性可以给qml去使用
  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.     return app.exec();
  24. }
复制代码
main.qml

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.12
  4. Window {
  5.     visible: true
  6.     width: SCREEN_WIDTH //从main.cpp中拿到这个变量的值
  7.     height: screen.desktopAvailableHeight/2 //screen可以获取到屏幕的相关大小。
  8.     title: qsTr("Hello World")
  9. }
复制代码
使用qmlRegisterType模板类

myobject.cpp

  1. #include "myobject.h"
  2. MyObject::MyObject(QObject *parent) : QObject(parent)
  3. {
  4. }
  5. MyObject *MyObject::getInst()
  6. {
  7.     static MyObject* obj = new MyObject;
  8.     return obj;
  9. }
  10. int MyObject::iValue() const
  11. {
  12.     return m_iValue;
  13. }
  14. void MyObject::setIValue(int iValue)
  15. {
  16.     m_iValue = iValue;
  17. }
  18. QString MyObject::sString() const
  19. {
  20.     return m_sString;
  21. }
  22. void MyObject::setSString(const QString &sString)
  23. {
  24.     m_sString = sString;
  25. }
复制代码
myobject.h

  1. #ifndef MYOBJECT_H
  2. #define MYOBJECT_H
  3. #include <QObject>
  4. #include <QtQml>
  5. class MyObject : public QObject
  6. {
  7.     Q_OBJECT
  8. //    QML_ELEMENT //声明为QML元素,低版本5.12 qt没有
  9. public:
  10.     explicit MyObject(QObject *parent = nullptr);
  11.     static MyObject* getInst();
  12.     void fun();
  13.     int iValue() const;
  14.     void setIValue(int iValue);
  15.     Q_PROPERTY(int iValue MEMBER m_iValue NOTIFY iValueChanged) //这个和下面那个都可以,经测试,使用MEMBER可以触发信号,下面的不行。
  16. //    Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged) //QT宏,iValue是声明的名称,可以通过名称获取,并且创建读取和设置的函数,在新加一个值改变的信号。
  17.     Q_PROPERTY(QString qstr READ sString() WRITE setSString NOTIFY sStringChanged) //QT宏,iValue是声明的名称,可以通过名称获取,并且创建读取和设置的函数,在新加一个值改变的信号。
  18.     QString sString() const;
  19.     void setSString(const QString &sString);
  20. private:
  21.     int m_iValue; //光标定位在属性上,键盘按下Alt+Enter 选择第一个
  22.     QString m_sString;
  23. signals:
  24.     void iValueChanged();
  25.     void sStringChanged();
  26. };
  27. #endif // MYOBJECT_H
复制代码
main.cpp

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQmlContext>
  4. #include <QScreen>
  5. #include <QRect>
  6. #include <QtDebug>
  7. #include "myobject.h"
  8. int main(int argc, char *argv[])
  9. {
  10.     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  11.     QGuiApplication app(argc, argv);
  12.     QQmlApplicationEngine engine;
  13.     //全局对象,上下文对象
  14.     QQmlContext* context = engine.rootContext();
  15.     QScreen*screen =  QGuiApplication::primaryScreen();
  16.     QRect rect = screen->availableGeometry();
  17.     qDebug()<<rect.width()/2;
  18.     context->setProperty("SCREEN_WIDTH",500 ); // 定义一个全局的属性可以给qml去使用
  19. //    context->setProperty("MyObject",MyObject::getInst()); //使用单例模式来创建一个对象。
  20.     qmlRegisterType<MyObject>("MyObj",1,0,"MyObject"); //myobj qml要导入的名称,主版本,次版本,使用对象
  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.     engine.load(url);
  28.     return app.exec();
  29. }
复制代码
main.qml

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.12
  4. import MyObj 1.0
  5. Window {
  6.     visible: true
  7. //    width: SCREEN_WIDTH //从main.cpp中拿到这个变量的值,12版本似乎拿不到。
  8.     width: screen.desktopAvailableWidth/2
  9.     height: screen.desktopAvailableHeight/2 //screen可以获取到屏幕的相关大小。
  10.     title: qsTr("Hello World")
  11.     property int  val: myobj.iValue
  12.     MyObject{ //C++中的对象。
  13.         id:myobj
  14.         iValue: 1
  15.         qstr: "12"
  16.         Component.onCompleted: {
  17.             console.log("ivalue = ",myobj.iValue," qstr = ",myobj.qstr)
  18.         }
  19.         onIValueChanged: { //这个信号来自与QT中的MODIFY信号,本人测试,在cpp中使用MEMBER方式可以绑定,其他不行
  20.             console.log("iValue changed = ",iValue)
  21.         }
  22.     }
  23.     Button{
  24.         onClicked: {
  25.             myobj.iValue =100
  26.             console.log("clicked myobj.iValue = ",myobj.iValue)
  27.         }
  28.     }
  29.     onValChanged: {
  30.         console.log("val = ",val)
  31.     }
  32. }
复制代码
QML端直接访问C++的函数

需要在C++类的函数使用Q_INVOKABLE宏,就可以完成直接访问,见下图。


 C++端直接调用qml函数



QML发送信号C++接收

方式一:在QML端绑定信号

main.qml

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.12
  4. import MyObj 1.0
  5. Window {
  6.     id:window
  7.     visible: true
  8.     width:600
  9.     height: 400
  10.     title: qsTr("QML与C++交互")
  11.     signal qmlSig(int i,string s)
  12.     MyObject{ //C++中的对象。
  13.         id:myobj
  14.         iValue: 1
  15.         m_sString: "m_sString_test"
  16.     }
  17.     Button{
  18.         onClicked: {
  19.             console.log("click")
  20.             qmlSig(10,"张三")  //点击发送信号,让C++端去接受他。
  21.         }
  22.     }
  23.     //方式一:
  24.     Connections{
  25.         target: window
  26.         onQmlSig:{
  27.             myobj.cppSlot(i,s) //直接调用槽函数。
  28.         }
  29.     }
  30. //    方式二
  31.     Component.onCompleted: {
  32.         qmlSig.connect(myobj.cppSlot)
  33.     }
  34. }
复制代码
方式二:在C++端绑定信号

main.cpp

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQmlContext>
  4. #include <QScreen>
  5. #include <QRect>
  6. #include <QtDebug>
  7. #include <QObject>
  8. #include "myobject.h"
  9. int main(int argc, char *argv[])
  10. {
  11.     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  12.     QGuiApplication app(argc, argv);
  13.     qDebug()<<QGuiApplication::platformName();
  14.     QQmlApplicationEngine engine;
  15.     //全局对象,上下文对象
  16.     QQmlContext* context = engine.rootContext();
  17.     QScreen*screen =  QGuiApplication::primaryScreen();
  18.     QRect rect = screen->availableGeometry();
  19.     qDebug()<<rect.width()/2;
  20.     context->setProperty("SCREEN_WIDTH",500 ); // 定义一个全局的属性可以给qml去使用
  21. //    context->setProperty("MyObject",MyObject::getInst()); //使用单例模式来创建一个对象。
  22.     qmlRegisterType<MyObject>("MyObj",1,0,"MyObject"); //myobj qml要导入的名称,主版本,次版本,使用对象
  23.     const QUrl url(QStringLiteral("qrc:/main.qml"));
  24.     QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
  25.                      &app, [url](QObject *obj, const QUrl &objUrl) {
  26.         if (!obj && url == objUrl)
  27.             QCoreApplication::exit(-1);
  28.     }, Qt::QueuedConnection);
  29.     engine.load(url);
  30.     //engine加载完成之后
  31.     auto list = engine.rootObjects(); //返回的是main.qml QML文件的所有对象。
  32.      //第一个元素的windows
  33.     QObject* window = list.first();
  34.     QObject* btn = list.first()->findChild<QObject*>("mybtn");
  35.     qDebug()<< window <<"|"<< window->objectName();
  36.     qDebug()<< btn <<"|"<< btn->objectName();
  37.     // 方式三
  38.     QObject::connect(window,SIGNAL(qmlSig(int,QString) ),MyObject::getInst(),SLOT(cppSlot(int,QString))  );
  39. //    MyObject* w = MyObject::getInst();
  40. //    QObject::connect(window, &QQuickWindowQmlImpl_QML_0::qmlSig, //这里无法用qt5的信号槽连接。
  41. //                      w,  &MyObject::cppSlot);
  42.     return app.exec();
  43. }
复制代码
C++端发送信号绑定qml函数

方式一

main.cpp

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQmlContext>
  4. #include <QScreen>
  5. #include <QRect>
  6. #include <QtDebug>
  7. #include <QObject>
  8. #include "myobject.h"
  9. int main(int argc, char *argv[])
  10. {
  11.     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  12.     QGuiApplication app(argc, argv);
  13.     qDebug()<<QGuiApplication::platformName();
  14.     QQmlApplicationEngine engine;
  15.     //全局对象,上下文对象
  16.     QQmlContext* context = engine.rootContext();
  17.     QScreen*screen =  QGuiApplication::primaryScreen();
  18.     QRect rect = screen->availableGeometry();
  19.     qDebug()<<rect.width()/2;
  20.     context->setProperty("SCREEN_WIDTH",500 ); // 定义一个全局的属性可以给qml去使用
  21. //    context->setProperty("MyObject",MyObject::getInst()); //使用单例模式来创建一个对象。
  22.     qmlRegisterType<MyObject>("MyObj",1,0,"MyObject"); //myobj qml要导入的名称,主版本,次版本,使用对象
  23.     const QUrl url(QStringLiteral("qrc:/main.qml"));
  24.     QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
  25.                      &app, [url](QObject *obj, const QUrl &objUrl) {
  26.         if (!obj && url == objUrl)
  27.             QCoreApplication::exit(-1);
  28.     }, Qt::QueuedConnection);
  29.     engine.load(url);
  30.     //engine加载完成之后
  31.     auto list = engine.rootObjects(); //返回的是main.qml QML文件的所有对象。
  32.      //第一个元素的windows
  33.     QObject* window = list.first();
  34.     QObject* btn = list.first()->findChild<QObject*>("mybtn");
  35.     qDebug()<< window <<"|"<< window->objectName();
  36.     qDebug()<< btn <<"|"<< btn->objectName();
  37.     // 方式三
  38.     QObject::connect(window,SIGNAL(qmlSig(int,QString) ),MyObject::getInst(),SLOT(cppSlot(int,QString))  );
  39. //    MyObject* w = MyObject::getInst();
  40. //    QObject::connect(window, &QQuickWindowQmlImpl_QML_0::qmlSig, //这里无法用qt5的信号槽连接。
  41. //                      w,  &MyObject::cppSlot);
  42.     return app.exec();
  43. }
复制代码
main.qml

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.12
  4. import MyObj 1.0
  5. Window {
  6.     id:window
  7.     visible: true
  8.     width:600
  9.     height: 400
  10.     objectName: "mywindow"
  11.     title: qsTr("QML与C++交互")
  12.     signal qmlSig(int i,string s)
  13.     MyObject{ //C++中的对象。
  14.         id:myobj
  15.         iValue: 1
  16.         m_sString: "m_sString_test"
  17.     }
  18.     Button{
  19.         objectName: "mybtn"
  20.         onClicked: {
  21.             console.log("click")
  22. //            myobj.cppSig(100,"test");
  23.             myobj.fun()
  24.         }
  25.     }
  26.     Connections{
  27.         target: myobj
  28.         onCppSig:{
  29.             console.log(i,s);
  30.         }
  31. //        function onCppSig(i,s){
  32. //            qmlSlot(i,s)
  33. //        }
  34.     }
  35. }
复制代码
myobject.cpp

  1. #include "myobject.h"
  2. MyObject::MyObject(QObject *parent) : QObject(parent)
  3. {
  4. }
  5. MyObject *MyObject::getInst()
  6. {
  7.     static MyObject* obj = new MyObject;
  8.     return obj;
  9. }
  10. void MyObject::fun()
  11. {
  12.     qDebug()<<__FUNCTION__;
  13.     emit cppSig(1,"C++");
  14. }
  15. int MyObject::iValue() const
  16. {
  17.     return m_iValue;
  18. }
  19. void MyObject::setIValue(int iValue)
  20. {
  21.     m_iValue = iValue;
  22. }
  23. QString MyObject::sString() const
  24. {
  25.     return m_sString;
  26. }
  27. void MyObject::setSString(const QString &sString)
  28. {
  29.     m_sString = sString;
  30. }
  31. void MyObject::cppSlot(int i, QString s)
  32. {
  33.     qDebug()<<__FUNCTION__ <<i<< s;
  34. }
复制代码
myobject.h

  1. #ifndef MYOBJECT_H
  2. #define MYOBJECT_H
  3. #include <QObject>
  4. #include <QtQml>
  5. class MyObject : public QObject
  6. {
  7.     Q_OBJECT
  8. //    QML_ELEMENT //声明为QML元素,低版本5.12 qt没有
  9. public:
  10.     explicit MyObject(QObject *parent = nullptr);
  11.     static MyObject* getInst();
  12.     Q_INVOKABLE void fun(); //Q_INVOKABLE宏可以让qml直接访问函数。
  13.     int iValue() const;
  14.     void setIValue(int iValue);
  15.     Q_PROPERTY(int iValue MEMBER m_iValue NOTIFY iValueChanged) //这个和下面那个都可以,经测试,使用MEMBER可以触发信号,下面的不行。
  16.     Q_PROPERTY(QString m_sString MEMBER m_sString NOTIFY sStringChanged) //QT宏,iValue是声明的名称,可以通过名称获取,并且创建读取和设置的函数,在新加一个值改变的信号。
  17.     QString sString() const;
  18.     void setSString(const QString &sString);
  19. private:
  20.     int m_iValue; //光标定位在属性上,键盘按下Alt+Enter 选择第一个
  21.     QString m_sString;
  22. public slots:
  23.     void cppSlot(int i,QString s);
  24. signals:
  25.     void iValueChanged();
  26.     void sStringChanged();
  27.     void cppSig(int i,QString s);
  28. };
  29. #endif // MYOBJECT_H
复制代码
方式二

main.cpp

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQmlContext>
  4. #include <QScreen>
  5. #include <QRect>
  6. #include <QtDebug>
  7. #include <QObject>
  8. #include "myobject.h"
  9. int main(int argc, char *argv[])
  10. {
  11.     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  12.     QGuiApplication app(argc, argv);
  13.     qDebug()<<QGuiApplication::platformName();
  14.     QQmlApplicationEngine engine;
  15.     qmlRegisterType<MyObject>("MyObj",1,0,"MyObject"); //通过模板创建
  16.     //通过单例创建
  17. //    qmlRegisterSingletoInstance("MyObj",1,0,"MyObject",MyObject::getInst() );//没有这个方法qt15引入。
  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.     //engine加载完成之后
  26.     auto list = engine.rootObjects(); //返回的是main.qml QML文件的所有对象。
  27.      //第一个元素的windows
  28.     QObject* window = list.first();
  29.     QObject* btn = list.first()->findChild<QObject*>("mybtn");
  30.     qDebug()<< window <<"|"<< window->objectName();
  31.     qDebug()<< btn <<"|"<< btn->objectName();
  32.     // 方式三
  33.     QObject::connect(window,SIGNAL(qmlSig(int,QString) ),MyObject::getInst(),SLOT(cppSlot(int,QString))  );
  34.     QObject::connect(MyObject::getInst(),SIGNAL(cppSig(QVariant,QVariant) ),window,SLOT(qmlSlot(QVariant,QVariant) )  );
  35.     return app.exec();
  36. }
复制代码
main.qml

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.12
  4. import MyObj 1.0
  5. Window {
  6.     id:window
  7.     visible: true
  8.     width:600
  9.     height: 400
  10.     objectName: "mywindow"
  11.     title: qsTr("QML与C++交互")
  12.     signal qmlSig(int i,string s)
  13.     MyObject{ //C++中的对象。
  14.         id:myobj
  15.         iValue: 1
  16.         m_sString: "m_sString_test"
  17.     }
  18.     Button{
  19.         objectName: "mybtn"
  20.         onClicked: {
  21.             console.log("click")
  22.             myobj.fun()  //MyObject.fun()
  23.         }
  24.     }
  25.     function qmlSlot(i,s){ // 参数类型 对应cpp端 都是QVariant
  26.         console.log(i,s);
  27.     }
  28.     Connections{
  29.         target: myobj
  30.         onCppSig:{
  31.             console.log(i,s);
  32.         }
  33. //        function onCppSig(i,s){
  34. //            qmlSlot(i,s)
  35. //        }
  36.     }
  37. }
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表