Qt - QML与C++数据交互详解
2024-01-09 17:44:16
文章目录
【极客技术传送门】 : https://blog.csdn.net/Engineer_LU/article/details/135149485
1 . 前言
Qml与C++通信有以下思路
- Qml调用C++的变量
- Qml调用C++的类
- Qml调用C++的方法
- Qml接收C++的信号
- C++调用Qml的方法
- C++接收Qml的信号
2 . Qml调用C++的变量
C++代码如下 :
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("HEIGHT",500);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
Qml代码如下 :
Window {
id: window
visible: true
width: 300
height: HEIGHT
title: qsTr("Hello World")
Component.onCompleted: {
console.log(window.width)
}
Button{
width: 100
height: 100
background: {
color:"black"
}
}
}
小结 :
- 以上代码的思路是C++通过engine.rootContext()->setContextProperty(“HEIGHT”,500);向Qml引擎注册一个HEIGHT名字变量,其中这里的500可以写成C++的变量,使其映射HEIGHT名字变量,然后就可以在Qml文件中访问HEIGHT该变量了
3 . Qml调用C++的类
C++代码如下 :
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include <QtQml>
class MyObject : public QObject
{
Q_OBJECT
Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(QString str READ getStr WRITE setStr NOTIFY strChanged)
public:
explicit MyObject(QObject *parent = nullptr);
public:
void setValue(int newValue);
int getValue();
void setStr(QString newStr);
QString getStr();
signals:
void valueChanged();
void strChanged();
private:
int m_value;
QString m_str;
};
#endif // MYOBJECT_H
#include "MyObject.h"
MyObject::MyObject(QObject *parent) : QObject(parent)
{
}
void MyObject::setValue(int newValue)
{
if(newValue == m_value)
return;
m_value = newValue;
emit valueChanged();
}
int MyObject::getValue()
{
return m_value;
}
void MyObject::setStr(QString newStr)
{
if(newStr == m_str)
return;
m_str = newStr;
emit strChanged();
}
QString MyObject::getStr()
{
return m_str;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
Qml代码如下 :
import MyObject 1.0
Window {
id: window
visible: true
width: 400
height: 500
title: qsTr("Hello World")
MyObject{
value: 10
str: "zhangsan"
onValueChanged: {
}
onStrChanged: {
}
Component.onCompleted: {
console.log(value,str)
}
}
}
小结 :
- 以上代码的思路是C++通过 qmlRegisterType<类名>(“Qml调用的类名称”,版本,“类名”); 例如上述的 qmlRegisterType(“MyObject”, 1, 0, “MyObject”); 向Qml注册一个类,使Qml可以基于这个类在Qml中创建对象。
- 其中C++类中要声明Q_OBJECT
- Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged)
这个是属性注册接口,其中注册了《读》《写》《信号》三个接口,其中Qml可以 读取/写入 C++的类成员变量,信号是C++调用后,Qml中用onValueChanged: {}作为槽 - int getValue();
void setValue(int newValue);
这两个是根据第3点的属性注册绑定的读写接口 - signals:
void valueChanged();
这个是根据第3点的属性注册绑定的信号接口,emit valueChanged(); 这样在C++调用后,就会发送信号,Qml中 onValueChanged: {} 触发响应接收
4 . Qml调用C++的方法
C++代码如下 :
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include <QtQml>
class MyObject : public QObject
{
Q_OBJECT
Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(QString str READ getStr WRITE setStr NOTIFY strChanged)
public:
explicit MyObject(QObject *parent = nullptr);
public:
Q_INVOKABLE void printMsg();
void setValue(int newValue);
int getValue();
void setStr(QString newStr);
QString getStr();
signals:
void valueChanged();
void strChanged();
private:
int m_value;
QString m_str;
};
#endif // MYOBJECT_H
#include "MyObject.h"
MyObject::MyObject(QObject *parent) : QObject(parent)
{
}
void MyObject::setValue(int newValue)
{
if(newValue == m_value)
return;
m_value = newValue;
emit valueChanged();
}
int MyObject::getValue()
{
return m_value;
}
void MyObject::setStr(QString newStr)
{
if(newStr == m_str)
return;
m_str = newStr;
emit strChanged();
}
QString MyObject::getStr()
{
return m_str;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
Qml代码如下 :
import MyObject 1.0
Window {
id: window
visible: true
width: 400
height: 500
title: qsTr("Hello World")
MyObject{
id: obj
value: 10
str: "zhangsan"
}
Button{
width: 50
height: 50
background: Rectangle{
color:"red"
}
onClicked: {
obj.printMsg()
}
}
}
小结 :
- public:
Q_INVOKABLE void printMsg();
这句话基于Qml调用C++的类交互的基础上增加,这样可以使得Qml创建对象后,可以调用C++类的方法
5 . Qml接收C++的信号
C++的代码如下
signals:
void sigMsg(int value,QString name);//在C++中调用 emit sigMsg(xxx,"xxx");
Qml的代码如下
MyObject{ id : obj
}
Connections{ //信号-槽连接方式一
target: obj
function onSigMsg(i,s){
console.log("/*-----------收到信号----------*/")
}
}
小结 :
- C++的类中定义信号,然后把类注册后,在Qml创建该类对象,用Connections把对象和onSigMsg(捕获类的信号)进行连接,Qml捕获信号的名字由C++类信号的名字前缀+on,后面首字母大写
6 . C++接收Qml的信号(在Qml中定义信号槽)
C++的代码如下
public slots:
void slotMsg(int value,QString name);
//实现
void MyObject::slotMsg(int value,QString name)
{
qDebug()<<__FUNCTION__<<" value = "<<value<<" name ="<<name;
}
Qml的代码如下
Window {
id: window
visible: true
width: 400
height: 500
title: qsTr("Hello World")
signal sendMsg(int value,string name) //增加信号
MyObject{
id: obj
value: 10
str: "zhangsan"
}
Button{
width: 50
height: 50
background: Rectangle{
color:"red"
}
onClicked: {
sendMsg(2,"zhangsan")
}
}
Component.onCompleted: { //信号-槽连接方式二
sendMsg.connect(obj.slotMsg)
}
}
小结 :
- 在Qml创建完毕之后把Qml的信号sendMsg连接到C++的类槽函数之中,这样在Qml完成Qml信号C++槽绑定。
7 . C++接收Qml的信号(在C++中定义信号槽)
Qml的代码如下
Window {
id: window
objectName: "window"
visible: true
width: 400
height: 500
title: qsTr("Hello World")
}
C++的代码如下
QQmlApplicationEngine engine;
qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
auto objs = engine.rootObjects();
qDebug()<<objs.first()->objectName();
MyObject *myobj = new MyObject();
auto objs = engine.rootObjects();
auto window = objs.first();
qDebug()<<objs.first()->objectName();
QObject::connect(window,SIGNAL(sendMsg(int,QString)),
myobj,SLOT(slotMsg(int,QString)));
小结 :
- Qml的第一个对象就是window,那么在C++中通过找到window的首地址,就可以基于这个首地址进行信号槽绑定,这样在C++完成Qml信号C++槽绑定。
8 . C++调用Qml的函数
Qml的代码如下
function test(value,name){ //供C++端调用的函数
console.log("test ",value,name)
}
C++的代码如下
QVariant ret;
QVariant arg1 = 123;
QVariant arg2 = "zhangsan";
QMetaObject::invokeMethod(window,"test",Q_RETURN_ARG(QVariant,ret)
,Q_ARG(QVariant,arg1)
,Q_ARG(QVariant,arg2));
小结 :
- 在Qml中创建一个test函数,在C++中通过元对象方法 QMetaObject::invokeMethod 来绑定调用Qml中的test函数,从而使得Qml可以接收C++的任意类型数据。
9 . 总结
以上描述了C++与QML数据交互的方式,大家可以根据以上方式扩展,模拟MVVM的模式代入框架实现简洁高效的前后端架构,谢谢观看。
技术交流QQ群 : 745662457
群内专注 - 问题答疑,项目外包,技术研究
文章来源:https://blog.csdn.net/Engineer_LU/article/details/135451398
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!