c++中加载qml文件方式

  1. 方式一:
  2. QQmlApplicationEngine engine;
  3. engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
  4. 方式二:
  5. QQuickView view;
  6. view.setSource(QUrl(QStringLiteral("qrc:///main.qml")));

两者的不同之处在于:

  1. 启动Qt Quick APP模式: QQmlApplicationEngine搭配Window。QQuickView搭配Item。
  2. 使用QQuickView显示QML文档,对窗口的控制权(比如设置窗口标题、Icon、窗口的最小尺寸等)在C++代码;而使用QQmlApplicationEngine加载以Window为根对象的QML文档,QML文档则拥有窗口的完整控制权,可以直接设置标题、窗口尺寸等属性。

    交互

    通过加载引擎engine获取到 QQmlContext指针对象(qml上下文对象、全局对象),通过改对象方法设置属性对qml的属性进行设置。

    1. QQmlApplicationEngine engine;
    2. QQmlContext* context = engine.rootContext();
    3. QScreen* screen = QGuiApplication::primaryScreen();
    4. QRect rect = screen->virtualGeometry();
    5. context->setContextProperty("WINDOW_WIDTH", rect.width());
    6. const QUrl url(QStringLiteral("qrc:/main.qml"));
    7. // const QUrl url(QStringLiteral("qrc:/myPopup.qml"));
    8. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    9. &app, [url](QObject *obj, const QUrl &objUrl) {
    10. if (!obj && url == objUrl)
    11. QCoreApplication::exit(-1);
    12. }, Qt::QueuedConnection);
    13. engine.load(url);
  1. Rectangle {
  2. width:840
  3. height: 460
  4. property int testValue: 0 //改属性可外部修改
  5. }
  6. Rectangle {
  7. width:840
  8. height: 460
  9. QtObject{
  10. id: attr
  11. property int testValue: 0 //改属性外部就不可访问了,相当于cpp private了,
  12. }
  13. Rectangle {
  14. width:840
  15. height: 460
  16. property alias attr: attributes //外部访问需要将id 使用别名开放给外部
  17. QtObject{
  18. id: attributes
  19. property int testValue: 0
  20. }
  21. Component.onCompleted: console.log(attributes.testValue) //内部访问需要通过id
  22. }

qml中对cpp属性进行访问:
创建cpp类

  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回去访问操作
  9. public:
  10. explicit MyObject(QObject *parent = nullptr);
  11. static MyObject* getInstance();
  12. int iValue() const;
  13. void setIValue(int newIValue);
  14. const QString &sString() const;
  15. void setSString(const QString &newSString);
  16. const QString &getSName() const;
  17. void setSName(const QString &newSName);
  18. int iAge() const;
  19. void setIAge(int newIAge);
  20. int getP_iHeight() const;
  21. void setP_iHeight(int newP_iHeight);
  22. signals:
  23. void iValueChanged();
  24. void sStringChanged();
  25. void sNameChanged();
  26. void iAgeChanged();
  27. void p_iHeightChanged();
  28. private:
  29. int m_iValue;
  30. QString m_sString;
  31. QString sName;
  32. int _iAge;
  33. int p_iHeight;
  34. //声明一个属性
  35. // Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged)
  36. // Q_PROPERTY(int iValue READ MEMBER m_iValue NOTIFY iValueChanged) //错误操作
  37. Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)
  38. Q_PROPERTY(QString sName READ getSName WRITE setSName NOTIFY sNameChanged)
  39. Q_PROPERTY(int iAge READ iAge WRITE setIAge NOTIFY iAgeChanged)
  40. Q_PROPERTY(int p_iHeight READ getP_iHeight WRITE setP_iHeight NOTIFY p_iHeightChanged)
  41. };
  42. #endif // MYOBJECT_H
  1. #include "myobject.h"
  2. MyObject::MyObject(QObject *parent)
  3. : QObject{parent}
  4. {
  5. }
  6. MyObject *MyObject::getInstance()
  7. {
  8. static MyObject* obj = new MyObject;
  9. return obj;
  10. }
  11. int MyObject::iValue() const
  12. {
  13. return m_iValue;
  14. }
  15. void MyObject::setIValue(int newIValue)
  16. {
  17. if (m_iValue == newIValue)
  18. return;
  19. m_iValue = newIValue;
  20. emit iValueChanged();
  21. }
  22. const QString &MyObject::sString() const
  23. {
  24. return m_sString;
  25. }
  26. void MyObject::setSString(const QString &newSString)
  27. {
  28. if (m_sString == newSString)
  29. return;
  30. m_sString = newSString;
  31. emit sStringChanged();
  32. }
  33. const QString &MyObject::getSName() const
  34. {
  35. return sName;
  36. }
  37. void MyObject::setSName(const QString &newSName)
  38. {
  39. if (sName == newSName)
  40. return;
  41. sName = newSName;
  42. emit sNameChanged();
  43. }
  44. int MyObject::iAge() const
  45. {
  46. return _iAge;
  47. }
  48. void MyObject::setIAge(int newIAge)
  49. {
  50. if (_iAge == newIAge)
  51. return;
  52. _iAge = newIAge;
  53. emit iAgeChanged();
  54. }
  55. int MyObject::getP_iHeight() const
  56. {
  57. return p_iHeight;
  58. }
  59. void MyObject::setP_iHeight(int newP_iHeight)
  60. {
  61. if (p_iHeight == newP_iHeight)
  62. return;
  63. p_iHeight = newP_iHeight;
  64. emit p_iHeightChanged();
  65. }

对cpp进行注册

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQuickView>
  4. #include <QQmlContext>
  5. #include <QScreen>
  6. #include <QRect>
  7. #include "myobject.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. QQmlApplicationEngine engine;
  15. QQmlContext* context = engine.rootContext();
  16. QScreen* screen = QGuiApplication::primaryScreen();
  17. QRect rect = screen->virtualGeometry();
  18. //注册的上下文对象 它是作用于全局的
  19. context->setContextProperty("windos_WIDTH", rect.width()/2);
  20. //方式1
  21. // MyObject obj;
  22. // context->setContextProperty("MyObject", &obj);
  23. // context->setContextProperty("MyObject", MyObject::getInstance());
  24. //方式2
  25. qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject"); //模板类型 模块名称 主版本号 次版本号 组件名称
  26. const QUrl url(QStringLiteral("qrc:/main.qml"));
  27. // const QUrl url(QStringLiteral("qrc:/myPopup.qml"));
  28. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
  29. &app, [url](QObject *obj, const QUrl &objUrl) {
  30. if (!obj && url == objUrl)
  31. QCoreApplication::exit(-1);
  32. }, Qt::QueuedConnection);
  33. engine.load(url);
  34. // QQuickView view;
  35. // view.setSource(QStringLiteral("qrc:/rectangle.qml"));
  36. return app.exec();
  37. }

qml中进行使用

  1. Window {
  2. property int windos_WIDTH: 200
  3. width: windos_WIDTH //会优先与内部属性windos_WIDTH绑定
  4. height: 480
  5. // property int value: width //这里是将这两个属性绑定,value随着width动态改变而改变
  6. property int value: myobj.iValue
  7. visible: true
  8. title: qsTr("Hello World")
  9. id: root
  10. MyObject{
  11. id: myobj
  12. iValue: 10
  13. sString: "zhangshan"
  14. // Component.onCompleted: {
  15. // console.log("MyObject completed")
  16. // }
  17. }
  18. // Component.completed: {
  19. // value = width //这里将width的当前值赋值给value,value不在与width存在动态绑定关系
  20. // }
  21. onWidthChanged: {
  22. console.log("onWidthChanged: ", width, " value: ", value)
  23. }
  24. onValueChanged: {
  25. console.log("onWidthChanged: ", width, " value: ", value)
  26. }
  27. Button{
  28. onClicked: myobj.iValue = 20 //iValue值被修改时会发送iValueChanged信号 通知value这个值被改变,value的值也会随着改变
  29. }
  30. }

qml中调用cpp方法:

  1. public:
  2. //添加宏 qml可访问,提起改对象已经注册过; 在private中声明会识别不到报错
  3. Q_INVOKABLE void func();
  4. void MyObject::func()
  5. {
  6. qDebug() << "func";
  7. }
  1. Button{
  2. onClicked: {
  3. myobj.func()
  4. myobj.iValue = 20 //iValue值被修改时会发送iValueChanged信号 通知value这个值被改变,value的值也会随着
  5. }
  6. }

qml与cpp信号槽的连接:

  1. signal qmlSig(int i, string s)
  2. Button{
  3. onClicked: {
  4. myobj.func()
  5. qmlSig(12, "wangwu")
  6. }
  7. }
  8. MyObject{
  9. id: myobj
  10. }
  11. //qml端绑定cpp槽函数:
  12. //方式1
  13. // Connections{
  14. // target: root
  15. // function onQmlSig(i, s){
  16. // myobj.cppSlot(i,s)
  17. // }
  18. // }
  19. //方式2
  20. Component.onCompleted: {
  21. qmlSig.connect(myobj.cppSlot)
  22. }
  23. //方式3 在cpp加载qml文件的地方进行绑定
  24. qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject"); //模板类型 模块名称 主版本号 次版本号 组件名称
  25. const QUrl url(QStringLiteral("qrc:/main.qml"));
  26. // const QUrl url(QStringLiteral("qrc:/myPopup.qml"));
  27. QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
  28. &app, [url](QObject *obj, const QUrl &objUrl) {
  29. if (!obj && url == objUrl)
  30. QCoreApplication::exit(-1);
  31. }, Qt::QueuedConnection);
  32. engine.load(url);
  33. //engine 加载完成后 load后
  34. auto list = engine.rootObjects();
  35. auto window = list.first();
  36. QObject::connect(window, SIGNAL(qmlSig(int, QString)),
  37. MyObject::getInstance(), SLOT(cppSlot(int, QString)));
  38. auto objName = list.first()->objectName();
  39. auto objChildName = list.first()->findChild<QObject*>("mybutton");
  40. qDebug() << objName << objChildName;

cpp信号触发qml槽函数

  1. function qmlSlot(i, s){//参数类型对应cpp都是QVariant类型
  2. console.log("qmlSlot ", i , " ", s)
  3. }
  4. Button{
  5. objectName: "mybutton"
  6. onClicked: {
  7. myobj.func()
  8. // myobj.cppSig(23, "liuzheng")
  9. qmlSig(12, "wangwu")
  10. }
  11. }
  12. MyObject{
  13. id: myobj
  14. }
  15. Connections{
  16. target: myobj
  17. function onCppSig(i, s){
  18. root.qmlSlot(i,s)
  19. }
  20. }

使用注册时映射一个cpp对象直接在qml中通过使用组件的方式进行调用cpp中的方法

  1. //模板类型 模块名称 主版本号 次版本号 组件名称 自定义模块对象
  2. qmlRegisterSingletonInstance("MyObj", 1, 0, "MyObject", MyObject::getInstance());
  1. Button{
  2. objectName: "mybutton"
  3. onClicked: {
  4. // myobj.func()
  5. // myobj.cppSig(23, "liuzheng")
  6. MyObject.func()
  7. qmlSig(12, "wangwu")
  8. }
  9. }
  10. // MyObject{
  11. // id: myobj
  12. // }
  13. Connections{
  14. // target: myobj
  15. target: MyObject
  16. function onCppSig(i, s){
  17. root.qmlSlot(i,s)
  18. }
  19. }
  1. QObject::connect(MyObject::getInstance(), SIGNAL(cppSig(int, QString)),
  2. window, SLOT(qmlSlot(int, QString)));