当前位置: 首页 > news >正文

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
群内专注 - 问题答疑,项目外包,技术研究

相关文章:

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

文章目录 1 . 前言2 . Qml调用C的变量3 . Qml调用C的类4 . Qml调用C的方法5 . Qml接收C的信号6 . C接收Qml的信号&#xff08;在Qml中定义信号槽&#xff09;7 . C接收Qml的信号&#xff08;在C中定义信号槽&#xff09;8 . C调用Qml的函数9 . 总结 【极客技术传送门】 : https…...

Kettle Local引擎使用记录(一)(基于Kettle web版数据集成开源工具data-integration源码)

Kettle Web &#x1f4da;第一章 前言&#x1f4da;第二章 demo源码&#x1f4d7;pom.xml引入Kettle引擎核心文件&#x1f4d7;java源码&#x1f4d5; controller&#x1f4d5; service&#x1f4d5; 其它&#x1f4d5; maven settings.xml &#x1f4d7;测试&#x1f4d5; 测试…...

Java--业务场景:在Spring项目启动时加载Java枚举类到Redis中(补充)

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

WPF 基础入门(资源字典)

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

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑电氢耦合和碳交易的电氢能源系统置信间隙鲁棒规划》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这标题涉及到一个复杂的能源系统规划问题&#xff0c;其中考虑了电氢耦合、碳交易和置信间隙鲁棒规划。以下是对标题各个部分的解读&#xff1a; 电氢耦…...

ubuntu设定时间与外部ntp同步

前言 在 Ubuntu 上&#xff0c;你可以通过配置 systemd-timesyncd 服务来与外部 NTP 服务器同步系统时间。下面是设置的步骤&#xff1a; 安装 NTP 工具&#xff1a; 如果你的系统中没有安装 ntpdate 工具&#xff0c;可以使用以下命令安装&#xff1a; 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问题&#xff0c;所以我们直接建模 这其实还是之前的那张图&#xff0c;我们把这个大的框架带入到之前的那个小车追击的问题中去&#xff0c;得到以下的一些具体的约束条件 CLF约束 L g V ( x ) u − δ ≤ − L f V ( x ) − λ V ( x ) …...

哈希表-散列表数据结构

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

C# 强制类型转换和as区别和不同使用场景

文章目录 1.强制类型转换2. as 运算符3.实例总结&#xff1a; 在C#中&#xff0c;as 和 强制类型转换&#xff08;例如 (T)value&#xff09;的主要区别在于它们处理类型转换不成功时的行为和适用场景&#xff1a; 1.强制类型转换 使用语法&#xff1a;Type variable (Type)…...

什么是 DDoS 攻击

布式拒绝服务 (DDoS) 攻击是一种恶意尝试,通过大量互联网流量淹没目标或其周围基础设施,从而破坏目标服务器、服务或网络的正常流量。 DDoS 攻击通过利用多个受感染的计算机系统作为攻击流量源来实现有效性。被利用的机器可以包括计算机和其他网络资源。 从高层来看,DDoS 攻…...

c++隐式类型转换与explicit

我们知道&#xff0c;一个float与int做运算时&#xff0c;系统会首先个int类型转换为float类型之后再进行运算&#xff0c;这种隐式类型转换也会发生在类中 看以下例子&#xff0c;定义一个类 class myTime { public:int Hour;myTime() {};myTime(int h) :Hour(h) {}; }; 在…...

BERT Intro

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

“To-Do Master“ GPTs:重塑任务管理的趣味与效率

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

npm安装vue,添加淘宝镜像

如果是第一次使用命令栏可能会遇到权限问题。 解决vscode无法运行npm和node.js命令的问题-CSDN博客 安装 在vscode上面的导航栏选择terminal打开新的命令栏 另外可能会遇到网络或者其他的问题&#xff0c;可以添加淘宝镜像 npm install -g cnpm --registryhttps://registry.…...

LeetCode 2707. 字符串中的额外字符

一、题目 1、题目描述 给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串&#xff0c;每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。 请你采取最优策略分割 s &#xff…...

Js进阶31-DOM 操作专题

1. JavaScript 的组成部分&#xff1a; ECMAScript&#xff1a;简称 ES&#xff0c;它是欧洲计算机协会&#xff0c;大概每年的六月中旬定制语法规范。DOM&#xff1a;全称 Document Object Model&#xff0c;即为文档对象类型。BOM&#xff1a;全称 Browser Object Model&…...

Hive之set参数大全-4

F 指定在使用 FETCH 命令提取查询结果时的序列化/反序列化器 hive.fetch.output.serde 是 Hive 的一个配置参数&#xff0c;用于指定在使用 FETCH 命令提取查询结果时的序列化/反序列化器。 以下是一个示例&#xff1a; -- 设置 hive.fetch.output.serde 为 org.apache.had…...

竞赛保研 基于深度学习的人脸识别系统

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

9.建造者模式

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

简单的MOV转MP4方法

1.下载腾讯的QQ影音播放器, 此播放器为绿色视频播放器, 除了播放下载好的视频外没有臃肿无用功能 官网 QQ影音 百度网盘链接&#xff1a;https://pan.baidu.com/s/1G0kSC-844FtRfqGnIoMALA 提取码&#xff1a;dh4w 2.用QQ影音打开MOV文件 3.右下角打开影音工具箱 , 选择截取…...

YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)

一、本文介绍 本文给大家带来的改进机制是ASF-YOLO(发布于2023.12月份的最新机制),其是特别设计用于细胞实例分割。这个模型通过结合空间和尺度特征,提高了在处理细胞图像时的准确性和速度。在实验中,ASF-YOLO在2018年数据科学竞赛数据集上取得了卓越的分割准确性和速度,…...

基于模块自定义扩展字段的后端逻辑实现(一)

目录 一&#xff1a;背景介绍 二&#xff1a;实现过程 三&#xff1a;字段标准化 四&#xff1a;数据存储 五&#xff1a;数据扩展 六&#xff1a;表的设计 一&#xff1a;背景介绍 最近要做一个系统&#xff0c;里面涉及一个模块是使用拖拉拽的形式配置模块使用的字段表…...

力扣:18.四数之和

一、做题链接&#xff1a;18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 二、题目分析 1.做这一道题之前本博主建议先看上一篇《三数之和》 2.题目分析 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重…...

.netcore 6 ioc注入的三种方式

1、定义接口 public interface MyInterceptorInterface 2、实现接口 public class MyInterceptorImpl : MyInterceptorInterface 在构造中增加以下代码&#xff0c;便于观察 static ConcurrentDictionary<string, string> keyValues new ConcurrentDictionary<s…...

Python轴承故障诊断 (十)基于VMD+CNN-Transfromer的故障分类

目录 1 变分模态分解VMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 故障VMD分解可视化 3 基于VMDCNN-Transformer的轴承故障诊断分类 3.1 定义VMD-CNN-Transformer分类网络模型 3.2 设置参数&#xff0c;训练模型 3.3 模型评估 代码、数据如下&#xff1a…...

【复习】人工智能 第7章 专家系统与机器学习

专家系统就是让机器人当某个领域的专家&#xff0c;但这章专家系统不咋考&#xff0c;主要靠书上没有的机器学习。 一、专家系统的基本组成 二、专家系统与传统程序的比较 &#xff08;1&#xff09;编程思想&#xff1a; 传统程序 数据结构 算法 专家系统 知识 推理 &…...

使用 Apache PDFBox 操作PDF文件

简介 Apache PDFBox库是一个开源的Java工具&#xff0c;专门用于处理PDF文档。它允许用户创建全新的PDF文件&#xff0c;编辑现有的PDF文档&#xff0c;以及从PDF文件中提取内容。此外&#xff0c;Apache PDFBox还提供了一些命令行实用工具。 Apache PDFBox提供了创建、渲染、…...

【Python 常用脚本及命令系列 3.2 -- 检测到弹框跳出然后关掉它--脚本实现】

文章目录 简介脚本实现 简介 在Python中&#xff0c;你可以使用第三方库如pyautogui和pygetwindow来检测屏幕上的弹框并关闭它。这些库可以模拟鼠标和键盘操作&#xff0c;也可以获取窗口信息。 首先&#xff0c;需要安装这些库&#xff08;如果你还没有安装的话&#xff09;&…...

junit单元测试:使用@ParameterizedTest 和 @CsvSource注解简化单元测试方法

在平常的开发工作中&#xff0c;我们经常需要写单元测试。比如&#xff0c;我们有一个校验接口&#xff0c;可能会返回多种错误信息。我们可以针对这个接口&#xff0c;写多个单元测试方法&#xff0c;然后将其场景覆盖全。那么&#xff0c;怎么才能写一个测试方法&#xff0c;…...

wordpress获取不同分类文章/电商seo是什么

绵绵的细雨挥洒在川蜀大地&#xff0c;到处都弥漫着泥土的清新和芳香。一大清早我就跑到了板房区的管委会&#xff0c;去赶前往北川任家坪的祭奠专用车。等我到了停车场后一看&#xff0c;好多人已经在那里排队。所以我就跑到了马路边去赶过往的班车。 一路上&#xff0c;我轻轻…...

用凡客建站做的网站有哪些/山东大学经济研究院

近两年像LOL、吃鸡这种竞技类游戏从来都是国内游戏市场中的常青树&#xff0c;尤其是英雄联盟&#xff0c;运营多年至今热度不减反增&#xff0c;保持这种状态实在难能可贵&#xff0c;其中很大的原因是这种MOBA类游戏往往靠技术说话&#xff0c;而至于氪金多少只能彰显在外观是…...

wordpress 创建菜单/简述搜索引擎优化的方法

外观数列是指具有以下特点的整数序列&#xff1a; d, d1, d111, d113, d11231, d112213111, … 它从不等于 1 的数字 d 开始&#xff0c;序列的第 n1 项是对第 n 项的描述。比如第 2 项表示第 1 项有 1 个 d&#xff0c;所以就是 d1&#xff1b;第 2 项是 1 个 d&#xff08;…...

西安网站建设高端/seo推广培训费用

一. 安装背景&#xff1a;VirtualBox下安装三台Centos6.8虚拟机&#xff08;一主:master, 两从:slave1,slave2&#xff09; Centos版本&#xff1a;CentOS-6.8-x86_64 网络配置&#xff1a;三台虚拟机配置静态IP&#xff0c;并配置主机名master,slave1,slave2 系统配置&#xf…...

做网站需要学会什么/新闻 近期大事件

为什么机器人能看到你&#xff1f; 因为它有自己的眼睛。机器视觉检测作为人工智能技术的一种。 可以通过利用计算机模拟人的视觉功能&#xff0c;从画面中提取关键信息&#xff0c;对其进行处理&#xff0c;最终用于实际的检测&#xff0c;测量和控制。 技能的最大特点是速度快…...

网站关键字怎么设置/北京seo外包

简介在数据挖掘的过程中&#xff0c;我们可能会经常遇到一些偏离于预测趋势之外的数据&#xff0c;通常我们称之为异常值。 通常将这样的一些数据的出现归为误差。有很多情况会出现误差&#xff0c;具体的情况需要就对待&#xff1a; 传感器故障   ->  忽略 数据输入错…...