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:840
height: 460
property int testValue: 0 //改属性可外部修改
}
Rectangle {
width:840
height: 460
QtObject{
id: attr
property int testValue: 0 //改属性外部就不可访问了,相当于cpp private了,
}
Rectangle {
width:840
height: 460
property alias attr: attributes //外部访问需要将id 使用别名开放给外部
QtObject{
id: attributes
property 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_OBJECT
QML_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);
#endif
QGuiApplication 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());
//方式2
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);
// QQuickView view;
// view.setSource(QStringLiteral("qrc:/rectangle.qml"));
return app.exec();
}
qml中进行使用
Window {
property int windos_WIDTH: 200
width: windos_WIDTH //会优先与内部属性windos_WIDTH绑定
height: 480
// property int value: width //这里是将这两个属性绑定,value随着width动态改变而改变
property int value: myobj.iValue
visible: true
title: qsTr("Hello World")
id: root
MyObject{
id: myobj
iValue: 10
sString: "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)
// }
// }
//方式2
Component.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: myobj
function 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: myobj
target: MyObject
function onCppSig(i, s){
root.qmlSlot(i,s)
}
}
QObject::connect(MyObject::getInstance(), SIGNAL(cppSig(int, QString)),
window, SLOT(qmlSlot(int, QString)));