c++中加载qml文件方式
方式一:QQmlApplicationEngine engine;engine.load(QUrl(QStringLiteral("qrc:///main.qml")));方式二:QQuickView view;view.setSource(QUrl(QStringLiteral("qrc:///main.qml")));
两者的不同之处在于:
- 启动Qt Quick APP模式: QQmlApplicationEngine搭配Window。QQuickView搭配Item。
使用QQuickView显示QML文档,对窗口的控制权(比如设置窗口标题、Icon、窗口的最小尺寸等)在C++代码;而使用QQmlApplicationEngine加载以Window为根对象的QML文档,QML文档则拥有窗口的完整控制权,可以直接设置标题、窗口尺寸等属性。
交互
通过加载引擎engine获取到 QQmlContext指针对象(qml上下文对象、全局对象),通过改对象方法设置属性对qml的属性进行设置。
QQmlApplicationEngine engine;QQmlContext* context = engine.rootContext();QScreen* screen = QGuiApplication::primaryScreen();QRect rect = screen->virtualGeometry();context->setContextProperty("WINDOW_WIDTH", rect.width());const QUrl url(QStringLiteral("qrc:/main.qml"));// const QUrl url(QStringLiteral("qrc:/myPopup.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);
Rectangle {width:840height: 460property int testValue: 0 //改属性可外部修改}Rectangle {width:840height: 460QtObject{id: attrproperty int testValue: 0 //改属性外部就不可访问了,相当于cpp private了,}Rectangle {width:840height: 460property alias attr: attributes //外部访问需要将id 使用别名开放给外部QtObject{id: attributesproperty int testValue: 0}Component.onCompleted: console.log(attributes.testValue) //内部访问需要通过id}
qml中对cpp属性进行访问:
创建cpp类
#ifndef MYOBJECT_H#define MYOBJECT_H#include <QObject>#include <QtQml>class MyObject : public QObject{Q_OBJECTQML_ELEMENT //告知编译器改类对象qml回去访问操作public:explicit MyObject(QObject *parent = nullptr);static MyObject* getInstance();int iValue() const;void setIValue(int newIValue);const QString &sString() const;void setSString(const QString &newSString);const QString &getSName() const;void setSName(const QString &newSName);int iAge() const;void setIAge(int newIAge);int getP_iHeight() const;void setP_iHeight(int newP_iHeight);signals:void iValueChanged();void sStringChanged();void sNameChanged();void iAgeChanged();void p_iHeightChanged();private:int m_iValue;QString m_sString;QString sName;int _iAge;int p_iHeight;//声明一个属性// Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged)// Q_PROPERTY(int iValue READ MEMBER m_iValue NOTIFY iValueChanged) //错误操作Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)Q_PROPERTY(QString sName READ getSName WRITE setSName NOTIFY sNameChanged)Q_PROPERTY(int iAge READ iAge WRITE setIAge NOTIFY iAgeChanged)Q_PROPERTY(int p_iHeight READ getP_iHeight WRITE setP_iHeight NOTIFY p_iHeightChanged)};#endif // MYOBJECT_H
#include "myobject.h"MyObject::MyObject(QObject *parent): QObject{parent}{}MyObject *MyObject::getInstance(){static MyObject* obj = new MyObject;return obj;}int MyObject::iValue() const{return m_iValue;}void MyObject::setIValue(int newIValue){if (m_iValue == newIValue)return;m_iValue = newIValue;emit iValueChanged();}const QString &MyObject::sString() const{return m_sString;}void MyObject::setSString(const QString &newSString){if (m_sString == newSString)return;m_sString = newSString;emit sStringChanged();}const QString &MyObject::getSName() const{return sName;}void MyObject::setSName(const QString &newSName){if (sName == newSName)return;sName = newSName;emit sNameChanged();}int MyObject::iAge() const{return _iAge;}void MyObject::setIAge(int newIAge){if (_iAge == newIAge)return;_iAge = newIAge;emit iAgeChanged();}int MyObject::getP_iHeight() const{return p_iHeight;}void MyObject::setP_iHeight(int newP_iHeight){if (p_iHeight == newP_iHeight)return;p_iHeight = newP_iHeight;emit p_iHeightChanged();}
对cpp进行注册
#include <QGuiApplication>#include <QQmlApplicationEngine>#include <QQuickView>#include <QQmlContext>#include <QScreen>#include <QRect>#include "myobject.h"int main(int argc, char *argv[]){#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);#endifQGuiApplication app(argc, argv);QQmlApplicationEngine engine;QQmlContext* context = engine.rootContext();QScreen* screen = QGuiApplication::primaryScreen();QRect rect = screen->virtualGeometry();//注册的上下文对象 它是作用于全局的context->setContextProperty("windos_WIDTH", rect.width()/2);//方式1// MyObject obj;// context->setContextProperty("MyObject", &obj);// context->setContextProperty("MyObject", MyObject::getInstance());//方式2qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject"); //模板类型 模块名称 主版本号 次版本号 组件名称const QUrl url(QStringLiteral("qrc:/main.qml"));// const QUrl url(QStringLiteral("qrc:/myPopup.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);// QQuickView view;// view.setSource(QStringLiteral("qrc:/rectangle.qml"));return app.exec();}
qml中进行使用
Window {property int windos_WIDTH: 200width: windos_WIDTH //会优先与内部属性windos_WIDTH绑定height: 480// property int value: width //这里是将这两个属性绑定,value随着width动态改变而改变property int value: myobj.iValuevisible: truetitle: qsTr("Hello World")id: rootMyObject{id: myobjiValue: 10sString: "zhangshan"// Component.onCompleted: {// console.log("MyObject completed")// }}// Component.completed: {// value = width //这里将width的当前值赋值给value,value不在与width存在动态绑定关系// }onWidthChanged: {console.log("onWidthChanged: ", width, " value: ", value)}onValueChanged: {console.log("onWidthChanged: ", width, " value: ", value)}Button{onClicked: myobj.iValue = 20 //iValue值被修改时会发送iValueChanged信号 通知value这个值被改变,value的值也会随着改变}}
qml中调用cpp方法:
public://添加宏 qml可访问,提起改对象已经注册过; 在private中声明会识别不到报错Q_INVOKABLE void func();void MyObject::func(){qDebug() << "func";}
Button{onClicked: {myobj.func()myobj.iValue = 20 //iValue值被修改时会发送iValueChanged信号 通知value这个值被改变,value的值也会随着}}
qml与cpp信号槽的连接:
signal qmlSig(int i, string s)Button{onClicked: {myobj.func()qmlSig(12, "wangwu")}}MyObject{id: myobj}//qml端绑定cpp槽函数://方式1// Connections{// target: root// function onQmlSig(i, s){// myobj.cppSlot(i,s)// }// }//方式2Component.onCompleted: {qmlSig.connect(myobj.cppSlot)}//方式3 在cpp加载qml文件的地方进行绑定qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject"); //模板类型 模块名称 主版本号 次版本号 组件名称const QUrl url(QStringLiteral("qrc:/main.qml"));// const QUrl url(QStringLiteral("qrc:/myPopup.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);//engine 加载完成后 load后auto list = engine.rootObjects();auto window = list.first();QObject::connect(window, SIGNAL(qmlSig(int, QString)),MyObject::getInstance(), SLOT(cppSlot(int, QString)));auto objName = list.first()->objectName();auto objChildName = list.first()->findChild<QObject*>("mybutton");qDebug() << objName << objChildName;
cpp信号触发qml槽函数
function qmlSlot(i, s){//参数类型对应cpp都是QVariant类型console.log("qmlSlot ", i , " ", s)}Button{objectName: "mybutton"onClicked: {myobj.func()// myobj.cppSig(23, "liuzheng")qmlSig(12, "wangwu")}}MyObject{id: myobj}Connections{target: myobjfunction onCppSig(i, s){root.qmlSlot(i,s)}}
使用注册时映射一个cpp对象直接在qml中通过使用组件的方式进行调用cpp中的方法
//模板类型 模块名称 主版本号 次版本号 组件名称 自定义模块对象qmlRegisterSingletonInstance("MyObj", 1, 0, "MyObject", MyObject::getInstance());
Button{objectName: "mybutton"onClicked: {// myobj.func()// myobj.cppSig(23, "liuzheng")MyObject.func()qmlSig(12, "wangwu")}}// MyObject{// id: myobj// }Connections{// target: myobjtarget: MyObjectfunction onCppSig(i, s){root.qmlSlot(i,s)}}
QObject::connect(MyObject::getInstance(), SIGNAL(cppSig(int, QString)),window, SLOT(qmlSlot(int, QString)));
