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"}}
}
小结 :
- 以上代码的思路是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)}}
}
小结 :
- 以上代码的思路是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_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()}}
}
小结 :
- 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("/*-----------收到信号----------*/")}
}
小结 :
- 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)}
}
小结 :
- 在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)));
小结 :
- 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
群内专注 - 问题答疑,项目外包,技术研究
相关文章:
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…...

Kettle Local引擎使用记录(一)(基于Kettle web版数据集成开源工具data-integration源码)
Kettle Web 📚第一章 前言📚第二章 demo源码📗pom.xml引入Kettle引擎核心文件📗java源码📕 controller📕 service📕 其它📕 maven settings.xml 📗测试📕 测试…...

Java--业务场景:在Spring项目启动时加载Java枚举类到Redis中(补充)
文章目录 前言步骤测试结果 前言 通过Java–业务场景:在Spring项目启动时加载Java枚举类到Redis中,我们成功将Java项目里的枚举类加载到Redis中了,接下来我们只需要写接口获取需要的枚举值数据就可以了,下面一起来编写这个接口吧。 步骤 在…...

WPF 基础入门(资源字典)
资源字典 每个Resources属性存储着一个资源字典集合。如果希望在多个项目之间共享资源的话,就可以创建一个资源字典。资源字段是一个简单的XAML文档,该文档就是用于存储资源的,可以通过右键项目->添加资源字典的方式来添加一个资源字典文件…...

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑电氢耦合和碳交易的电氢能源系统置信间隙鲁棒规划》
本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这标题涉及到一个复杂的能源系统规划问题,其中考虑了电氢耦合、碳交易和置信间隙鲁棒规划。以下是对标题各个部分的解读: 电氢耦…...
ubuntu设定时间与外部ntp同步
前言 在 Ubuntu 上,你可以通过配置 systemd-timesyncd 服务来与外部 NTP 服务器同步系统时间。下面是设置的步骤: 安装 NTP 工具: 如果你的系统中没有安装 ntpdate 工具,可以使用以下命令安装: sudo apt-get updat…...

DataFrame详解
清洗相关的API 清洗相关的API: 1.去重API: dropDupilcates 2.删除缺失值API: dropna 3.替换缺失值API: fillna 去重API: dropDupilcates dropDuplicates(subset):删除重复数据 1.用来删除重复数据,如果没有指定参数subset,比对行中所有字段内容,如果全部相同,则认为是重复数据,…...

控制障碍函数(Control Barrier Function,CBF) 三、代码
三、代码实现 3.1、模型 这是一个QP问题,所以我们直接建模 这其实还是之前的那张图,我们把这个大的框架带入到之前的那个小车追击的问题中去,得到以下的一些具体的约束条件 CLF约束 L g V ( x ) u − δ ≤ − L f V ( x ) − λ V ( x ) …...

哈希表-散列表数据结构
1、什么是哈希表? 哈希表也叫散列表,哈希表是根据关键码值(key value)来直接访问的一种数据结构,也就是将关键码值(key value)通过一种映射关系映射到表中的一个位置来加快查找的速度,这种映射关系称之为哈希函数或者散列函数&…...

C# 强制类型转换和as区别和不同使用场景
文章目录 1.强制类型转换2. as 运算符3.实例总结: 在C#中,as 和 强制类型转换(例如 (T)value)的主要区别在于它们处理类型转换不成功时的行为和适用场景: 1.强制类型转换 使用语法:Type variable (Type)…...
什么是 DDoS 攻击
布式拒绝服务 (DDoS) 攻击是一种恶意尝试,通过大量互联网流量淹没目标或其周围基础设施,从而破坏目标服务器、服务或网络的正常流量。 DDoS 攻击通过利用多个受感染的计算机系统作为攻击流量源来实现有效性。被利用的机器可以包括计算机和其他网络资源。 从高层来看,DDoS 攻…...
c++隐式类型转换与explicit
我们知道,一个float与int做运算时,系统会首先个int类型转换为float类型之后再进行运算,这种隐式类型转换也会发生在类中 看以下例子,定义一个类 class myTime { public:int Hour;myTime() {};myTime(int h) :Hour(h) {}; }; 在…...

BERT Intro
继续NLP的学习,看完理论之后再看看实践,然后就可以上手去kaggle做那个入门的project了orz。 参考: 1810.04805.pdf (arxiv.org) BERT 论文逐段精读【论文精读】_哔哩哔哩_bilibili (强推!)2023李宏毅讲解大模型鼻祖BERT,一小时…...

“To-Do Master“ GPTs:重塑任务管理的趣味与效率
有 GPTs 访问权限的可以点击链接进行体验:https://chat.openai.com/g/g-IhGsoyIkP-to-do-master 部署私人的 To-Do Master 教程:https://github.com/Reborn14/To-Do-Master/tree/main 引言 在忙碌的日常生活中,有效地管理日常任务对于提高生…...

npm安装vue,添加淘宝镜像
如果是第一次使用命令栏可能会遇到权限问题。 解决vscode无法运行npm和node.js命令的问题-CSDN博客 安装 在vscode上面的导航栏选择terminal打开新的命令栏 另外可能会遇到网络或者其他的问题,可以添加淘宝镜像 npm install -g cnpm --registryhttps://registry.…...
LeetCode 2707. 字符串中的额外字符
一、题目 1、题目描述 给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串,每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。 请你采取最优策略分割 s ÿ…...
Js进阶31-DOM 操作专题
1. JavaScript 的组成部分: ECMAScript:简称 ES,它是欧洲计算机协会,大概每年的六月中旬定制语法规范。DOM:全称 Document Object Model,即为文档对象类型。BOM:全称 Browser Object Model&…...
Hive之set参数大全-4
F 指定在使用 FETCH 命令提取查询结果时的序列化/反序列化器 hive.fetch.output.serde 是 Hive 的一个配置参数,用于指定在使用 FETCH 命令提取查询结果时的序列化/反序列化器。 以下是一个示例: -- 设置 hive.fetch.output.serde 为 org.apache.had…...

竞赛保研 基于深度学习的人脸识别系统
前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的人脸识别系统 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/…...

9.建造者模式
文章目录 一、介绍二、代码三、实际使用总结 一、介绍 建造者模式旨在将一个复杂对象的构建过程和其表示分离,以便同样的构建过程可以创建不同的表示。这种模式适用于构建对象的算法(构建过程)应该独立于对象的组成部分以及它们的装配方式的…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
起重机起升机构的安全装置有哪些?
起重机起升机构的安全装置是保障吊装作业安全的关键部件,主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理: 一、超载保护装置(核心安全装置) 1. 起重量限制器 功能:实时监测起升载荷&a…...

python可视化:俄乌战争时间线关键节点与深层原因
俄乌战争时间线可视化分析:关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一,自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具,系统分析这场战争的时间线、关键节点及其背后的深层原因,全面…...
C#最佳实践:为何优先使用as或is而非强制转换
C#最佳实践:为何优先使用as或is而非强制转换 在 C# 的编程世界里,类型转换是我们经常会遇到的操作。就像在现实生活中,我们可能需要把不同形状的物品重新整理归类一样,在代码里,我们也常常需要将一个数据类型转换为另…...
基于Java项目的Karate API测试
Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...