Qt - QML与C++数据交互详解

文章目录

  • 1 . 前言
  • 2 . Qml调用C++的变量
  • 3 . Qml调用C++的类
  • 4 . Qml调用C++的方法
  • 5 . Qml接收C++的信号
  • 6 . C++接收Qml的信号(在Qml中定义信号槽)
  • 7 . C++接收Qml的信号(在C++中定义信号槽)
  • 8 . C++调用Qml的函数
  • 9 . 总结


【极客技术传送门】 : 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: windowvisible: truewidth: 300height: HEIGHTtitle: qsTr("Hello World")Component.onCompleted: {console.log(window.width)}Button{width: 100height: 100background: {color:"black"}}
}

小结 :

  1. 以上代码的思路是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_OBJECTQ_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.0Window {id: windowvisible: truewidth: 400height: 500title: qsTr("Hello World")MyObject{value: 10str: "zhangsan"onValueChanged: {}onStrChanged: {}Component.onCompleted: {console.log(value,str)}}
}

小结 :

  1. 以上代码的思路是C++通过 qmlRegisterType<类名>(“Qml调用的类名称”,版本,“类名”); 例如上述的 qmlRegisterType(“MyObject”, 1, 0, “MyObject”); 向Qml注册一个类,使Qml可以基于这个类在Qml中创建对象。
  2. 其中C++类中要声明Q_OBJECT
  3. Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged)
    这个是属性注册接口,其中注册了《读》《写》《信号》三个接口,其中Qml可以 读取/写入 C++的类成员变量,信号是C++调用后,Qml中用onValueChanged: {}作为槽
  4. int getValue();
    void setValue(int newValue);
    这两个是根据第3点的属性注册绑定的读写接口
  5. 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_OBJECTQ_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.0Window {id: windowvisible: truewidth: 400height: 500title: qsTr("Hello World")MyObject{id: objvalue: 10str: "zhangsan"}Button{width: 50height: 50background: Rectangle{color:"red"}onClicked: {obj.printMsg()}}
}

小结 :

  1. 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: objfunction onSigMsg(i,s){console.log("/*-----------收到信号----------*/")}
}

小结 :

  1. 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: windowvisible: truewidth: 400height: 500title: qsTr("Hello World")signal sendMsg(int value,string name)   //增加信号MyObject{id: objvalue: 10str: "zhangsan"}Button{width: 50height: 50background: Rectangle{color:"red"}onClicked: {sendMsg(2,"zhangsan")}}Component.onCompleted: {    //信号-槽连接方式二sendMsg.connect(obj.slotMsg)}
}

小结 :

  1. 在Qml创建完毕之后把Qml的信号sendMsg连接到C++的类槽函数之中,这样在Qml完成Qml信号C++槽绑定。

7 . C++接收Qml的信号(在C++中定义信号槽)

Qml的代码如下

Window {id: windowobjectName: "window"visible: truewidth: 400height: 500title: 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)));

小结 :

  1. 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));

小结 :

  1. 在Qml中创建一个test函数,在C++中通过元对象方法 QMetaObject::invokeMethod 来绑定调用Qml中的test函数,从而使得Qml可以接收C++的任意类型数据。

9 . 总结

以上描述了C++与QML数据交互的方式,大家可以根据以上方式扩展,模拟MVVM的模式代入框架实现简洁高效的前后端架构,谢谢观看。

技术交流QQ群 : 745662457
群内专注 - 问题答疑,项目外包,技术研究

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/608421.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能寻迹避障清障机器人设计(摘 要)

摘 要 现今&#xff0c;智能机器人已经逐步走进人们的生活&#xff0c;智能扫地机器人、智能早教机、智能洗碗机等家用机器人早已屡见不鲜&#xff0c;但在智能工程车方面就接近空白。至此&#xff0c;一款智能寻迹避障清障测距跟随机器人开始浮现水面。 纵观世界&#xff0c…

混淆技术概论

混淆技术概论 引言 在逆向工程领域&#xff0c;混淆技术是一种非常重要的技术手段&#xff0c;通过打破人们的思维惯性&#xff0c;使得逆向分析变得更加困难。本文将会介绍混淆技术的概念、分类及其应用&#xff0c;以及如何使用IPA Guard进行iOS IPA重签名。 混淆技术概述…

SCT82A30大幅解决控制芯片发热难题,超宽输入电压范围,里程碑级作品

如何解决控制芯片发热问题 在高压大电流降压应用中&#xff0c;很多工程师在产品设计中遇到的比较头疼的问题是&#xff0c;如何解决控制芯片自身发热的问题&#xff0c;特别是48V以上的输入电压。 发热问题产生的原因是&#xff1a;控制芯片Vcc由内部LDO从Vin取电&#xff0c…

计算机体系结构流水线学习记录

一、知识点汇总 1.理想情况下&#xff0c;流水线能够实现 n 倍的吞吐率加速比&#xff08;n为流水线深度&#xff09;&#xff0c;但是流水线深度并非越大越好&#xff0c;因为流水线的深度会影响到性能和功耗之间的平衡。 2.RISC&#xff1a;Reduced Instruction Set Comput…

微软最新研究成果:使用GPT-4合成数据来训练AI模型,实现SOTA!

文本嵌入是各项NLP任务的基础&#xff0c;用于将自然语言转换为向量表示。现有的大部分方法通常采用复杂的多阶段训练流程&#xff0c;先在大规模数据上训练&#xff0c;再在小规模标注数据上微调。此过程依赖于手动收集数据制作正负样本对&#xff0c;缺乏任务的多样性和语言多…

vue 组件之间通信的方式

1.父向子版 父组件设置自定义属性 子组件props接收 //父组件环境下 <my-demo :自定义属性名字"要传递的具体值"></my-demo> //子组件 export default{ props:[自定义属性名字] } 2.子向父版 父组件设置自定义方法并绑定接收的方法 子组件触发方法 //…

Android简单控件

1.文本显示 设置文本内容的两种方式&#xff1a; 在XML文件中通过属性 android:text 设置文本 <resources><string name"app_name">chapter03</string><string name"hello">你好&#xff0c;世界</string> </resources&…

人逢三六九,运势低迷路难走

很多人都希望自己各方面的运势都能够朝着好的方向旺盛发展&#xff0c;我们的运势将会如何发展跟我们的出生时间是离不开关系的。我们的祖先为了后人着想&#xff0c;不犯他们犯过的错误&#xff0c;少走一些弯路&#xff0c;总结了多年来的生活经验&#xff0c;创造出了一句句…

前端表格使用vxe-table进行渲染,使用el-select进行选择合适的条件查询,且给el-select默认赋值及使用i18n进行翻译

前端表格使用vxe-table进行渲染&#xff0c;使用el-select进行选择合适的条件查询&#xff0c;且给el-select默认赋值及使用i18n进行翻译 一、项目需求及项目实现 一、项目需求及项目实现 表格页面使用vxe-table进行渲染&#xff0c;查询区使用el-select进行选择&#xff0c;且…

JS、Python实现AES加密,Python实现RSA加密,读txt每行数据存入列表

1. JS实现AES加密 var CryptoJS require(./package); // package文件是cryptoJS var plaintext {"did":"a","dname":"Chrome"};var key CryptoJS.lib.WordArray.create([929392180,1650538033,1681023538,1647784550 ]); var i…

拼多多API:从数据中挖掘商业价值的力量

随着大数据时代的来临&#xff0c;数据已经成为企业决策和创新的基石。拼多多API作为电商领域的重要接口&#xff0c;为企业提供了从数据中挖掘商业价值的机会。通过拼多多API&#xff0c;企业可以获取丰富的用户数据、商品数据和交易数据&#xff0c;从而深入了解市场需求、优…

metric,log

Metric&#xff08;指标&#xff09;和 Log&#xff08;日志&#xff09;是两种不同的监控数据类型&#xff0c;它们在监控和故障排查中有不同的用途和特点。 ### Metric&#xff08;指标&#xff09;: 1. 定义&#xff1a; Metric 是定量的度量&#xff0c;通常是数值或计数…

C++11新特性(也称c++2.0)

目录 1.输出C版本&#xff1a;cout << __cplusplus << endl; 2.Uniform Initialization(一致性初始化) 3.initializer_list&#xff08;形参&#xff09; 4.explicit 5.for循环的新用法 6.default和delete 7.Alias Template&#xff08;模板化名&#xff09…

LLaMA Efficient Tuning

文章目录 LLaMA Efficient Tuning安装 数据准备浏览器一体化界面单 GPU 训练 train_bash1、预训练 pt2、指令监督微调 sft3、奖励模型训练 rm4、PPO 训练 ppo5、DPO 训练 dpo 多 GPU 分布式训练1、使用 Huggingface Accelerate2、使用 DeepSpeed 导出微调后的模型 export_model…

Volcano Scheduler调度器源码解析

Volcano Scheduler调度器源码解析 本文从源码的角度分析Volcano Scheduler相关功能的实现。 本篇Volcano版本为v1.8.0。 Volcano项目地址: https://github.com/volcano-sh/volcano controller命令main入口: cmd/scheduler/main.go controller相关代码目录: pkg/scheduler 关联…

Vue3.x+Echarts (可视化界面)

Vue3.0Echarts &#xff08;可视化界面&#xff09; 1. 简介1.1 技术选型1.2 ECharts支持的数据格式1.3 ECharts使用步骤 2. ECharts图形2.1 通用配置2.2 柱状图2.3 折线图2.4 散点图2.5 直角坐标系常用配置2.6 饼图2.7 地图2.8 雷达图2.9 仪表盘2.10 小结 3. Vue3.2ECharts5数…

RecombiMAb anti-mouse VEGFR-2

DC101-CP132单克隆抗体是原始DC101单克隆的重组嵌合型抗体。可变结构域序列与原始DC101相同&#xff0c;但是恒定区序列已经从大鼠IgG1变为小鼠IgG2a。DC101-CP132单克隆抗体像原始大鼠IgG1抗体一样&#xff0c;不包含Fc突变。 DC101-CP132单克隆抗体能与小鼠VEGFR-2(血管内皮生…

docker容器内,将django项目数据库改为postgresql

容器为ubuntu20.04版本&#xff0c;新建了一套django项目&#xff0c;使用的默认sqllit3&#xff0c;换为postgresql&#xff0c;容器里安装postgresql方法 步骤1: 安装PostgreSQL数据库 # 打开一个bash会话在你的容器中 docker exec -it <container_id_or_name> bash#…

ZGC垃圾收集器介绍

ZGC&#xff08;The Z Garbage Collector&#xff09;是JDK 11中推出的一款低延迟垃圾回收器&#xff0c;它的设计目标包括&#xff1a; 停顿时间不超过10ms&#xff1b;停顿时间不会随着堆的大小&#xff0c;或者活跃对象的大小而增加&#xff1b;支持8MB~4TB级别的堆&#x…

【开题报告】基于JavaWeb的母婴用品在线商城的设计与实现

1.选题背景 随着社会经济的发展和人们生活水平的提高&#xff0c;母婴用品市场逐渐壮大。同时&#xff0c;互联网的普及和电子商务的兴起使得线上购物成为了人们方便快捷的购物方式之一。传统的实体母婴用品店面受到了线上商城的冲击&#xff0c;因此建立一个方便、快捷的在线…