22. QML与C++交互---C++调用QML中的函数

news/2024/4/20 12:29:34/文章来源:https://blog.csdn.net/FY_13781298928/article/details/129198951

1. 说明

在QML与C++混合开发时,QML界面元素可以通过某种方式去调用C++中的函数,相关文章可查看C++注册函数和属性供QML使用。但是,在某种情况下也需要在C++端去调用QML中定义的函数,完成相应的功能,本篇文章将简单介绍几种方式进行实现。

2. 方式一

这种方式比较灵活,可以在QML界面的某个控件中触发C++去调用函数,也就是QML先去调用C++当中的某一个函数A,这个函数A再去调用QML中的函数,好处在于我们可以控制函数执行的时间。
第一步:自定义一个类并命名为callqmlfunc,在其中定义一个函数sayHello,这个函数是需要在QML端调用的,代码如下:
callqmlfunc.h:

#ifndef CALLQMLFUNC_H
#define CALLQMLFUNC_H#include <QObject>
#include <QDebug>
#include <QQmlApplicationEngine>class CallQMLFunc : public QObject
{Q_OBJECT
public:explicit CallQMLFunc(QObject *parent = nullptr);Q_INVOKABLE void sayHello();//需要在QML中调用,所以要用 Q_INVOKABLE 修饰signals:};#endif // CALLQMLFUNC_H

第二步:将上面的自定义类注册到QML的上下文背景中,可参考文章:C++类注册到QML中使用,这样才能在QML中调用类中的sayHello函数。在注册C++类时关键一步是需要直接指定其父对象,这样在下文使用时才能根据父对象找到其内部的对应名称的函数。相关代码如下:
在main.cpp中进行注册:

//第一种方式:(函数在根节点中)注册类时指定父类,在QML中像正常类对象一样调用函数
QObject *root=engine.rootObjects().at(0);//获取QML中的根节点,就是Window
qDebug()<<root->objectName();//这里的输出为:mainWindow
CallQMLFunc *callQmlFunc = new CallQMLFunc(root);//创建C++类对象,并指定其父类为 root ,也就是根节点
engine.rootContext()->setContextProperty("callQmlFunc",callQmlFunc);//将类对象注册到QML的上下文背景中

如果QML中函数没有写在根节点下,而是写到了其他子节点下,此时我们可以给子节点设置以下 objectName 属性,然后使用下面的方式去查找父类,也是可以的:

//第一种方式:(函数在根节点中)注册类时指定父类,在QML中像正常类对象一样调用函数
QObject *root=engine.rootObjects().at(0);//获取QML中的根节点,就是Window
QObject* parentObj = root->findChild<QObject*>("mainText");//根据根节点查找字节点
CallQMLFunc *callQmlFunc = new CallQMLFunc(parentObj);//创建C++类对象,并指定其父类为 parentObj ,也就是根节点
engine.rootContext()->setContextProperty("callQmlFunc",callQmlFunc);//将类对象注册到QML的上下文背景中

第三步:注册完成后,在callqmlfunc.cpp文件中调用QML中的函数
callqmlfunc.cpp:

#include "callqmlfunc.h"CallQMLFunc::CallQMLFunc(QObject *parent): QObject{parent}
{}void CallQMLFunc::sayHello()
{//调用QML中函数sayHello//注意://第一个参数是父类,这里能够使用parent(),是因为在上面注册C++类到QML中时已经指定了父对象//第二个参数是需要调用的QML中的函数名称//第三个参数是传递到QML中函数的参数,参数类型必须是QVariant类型QMetaObject::invokeMethod(parent(),"sayHello",Q_ARG(QVariant,"Hello..."));
}

注意:
如果QML中函数有返回值,C++调用这个函数之后,需要接收函数的返回值,那么可以采用下述方式:

void CallQMLFunc::sayHello()
{QVariant ret;//声明变量用于接收返回值//此时第三个参数是接收返回值的变量,类型必须是QVariant类型//第四个参数是传递到QML中函数的参数,参数类型必须是QVariant类型QMetaObject::invokeMethod(parent(),"sayHello",Q_RETURN_ARG(QVariant,ret),Q_ARG(QVariant,"Hello..."));qDebug()<<ret.toString();//输出为:"hahahaha..."
}

3. 方式二

这种方式与方式一的不同点在于:注册C++类时并未指定父对象是谁,无法使用QML中的元素控制函数的执行,而是在main.cpp中直接调用了QML中的函数(了解即可,用处不大),相关代码如下:
main.cpp:

auto root2 = engine.rootObjects();
auto parentObj = root2.first()->findChild<QObject*>("mainText");
QMetaObject::invokeMethod(parentObj,"sayHello",Q_ARG(QVariant,"Hello..."));

4. QML主界面代码:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15Window {id:rootobjectName: "mainWindow"	//设置控件属性名,供C++中的engine查找width: 640height: 480visible: truetitle: qsTr("Hello Signal")//定义函数,供C++调用function sayHello(_str){console.log(_str)helloText.text = _strreturn "hahahaha..."}Button{id:btnobjectName: "helloBtn" //设置控件属性名,供C++中的engine查找width: 100height: 50anchors.horizontalCenter: parent.horizontalCenteranchors.top:parent.topanchors.topMargin: 10text: "callQmlFunc"onClicked: {callQmlFunc.sayHello()}}Text{id:helloTextobjectName: "mainText" //设置控件属性名,供C++中的engine查找width: 100height: 50anchors.centerIn: parentfont.pixelSize: 20//定义函数,供C++调用function sayHello(_str){console.log(_str)helloText.text = _strreturn "hahahaha..."}}}

持续更新中,请大家多多关注…

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

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

相关文章

Tapdata 和 Databend 数仓数据同步实战

作者&#xff1a;韩山杰https://github.com/hantmacDatabend Cloud 研发工程师基础架构在云计算时代也发生着翻天地覆的变化&#xff0c;对于业务的支持变成了如何能利用好云资源实现降本增效&#xff0c;同时更好的支撑业务也成为新时代技术人员的挑战。 本篇文章通过&#xf…

删除MySQL表中的重复数据?

前言 一般我们将数据存储在MySQL数据库中&#xff0c;它允许我们存储重复的数据。但是往往重复的数据是作废的、没有用的数据&#xff0c;那么通常我们会使用数据库的唯一索引 unique 键作为限制。问题来了啊&#xff0c;我还没有创建唯一索引捏&#xff0c;数据就重复了&…

jianzhiOffer第二版难重点记录

04. 二维数组中的查找https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/ 思路&#xff1a;可以每层用以恶搞二分查找&#xff0c;优化思路&#xff1a;从左下角出发直接用二分。 ​​​​​​07. 重建二叉树https://leetcode.cn/problems/zhong-jian-er-cha…

springboot+vue.js高校大学生选课成绩管理系统javaweb

本课题要求实现一套学生成绩管理系统&#xff0c;系统主要包括管理员&#xff0c;学生和教师三大模块 (a) 管理员&#xff1b;管理员进入系统主要功能包括首页&#xff0c;个人中心&#xff0c;教师管理&#xff0c;学生管理&#xff0c;公告信息管理&#xff0c;课程类型管理&…

Android自定义View实现横向的双水波纹进度条

效果图&#xff1a;网上垂直的水波纹进度条很多&#xff0c;但横向的很少&#xff0c;将垂直的水波纹改为水平的还遇到了些麻烦&#xff0c;现在完善后发布出来&#xff0c;希望遇到的人少躺点坑。思路分析整体效果可分为三个&#xff0c;绘制圆角背景和圆角矩形&#xff0c;绘…

Linux学习(7.5)linux目录配置与重点回顾

鸟哥的 Linux 私房菜 -- Linux 的文件权限与目录配置 (vbird.org) 怎么记啊&#xff0c;直接点进去看吧 目录 Linux目录配置的依据--FHS 绝对路径与相对路径 重点回顾 以下内容转载自鸟哥的Linux私房菜 Linux目录配置的依据--FHS 是希望让使用者可以了解到已安装软件通常…

16、变量、流程控制与游标

文章目录1 变量1.1 系统变量1.1.1 系统变量分类1.1.2 查看系统变量1.2 用户变量1.2.1 用户变量分类1.2.2 会话用户变量1.2.3 局部变量1.2.4 对比会话用户变量与局部变量2 定义条件与处理程序2.1 案例分析2.2 定义条件2.3 定义处理程序2.4 案例解决3 流程控制3.1 分支结构之 IF3…

嵌入式系统硬件设计与实践(学习方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 刚读书的时候&#xff0c;对什么是嵌入式&#xff0c;其实并不太清楚。等到自己知道的时候&#xff0c;已经毕业很多年了。另外对于计算机毕业的学…

Python近红外光谱分析与机器学习、深度学习方法融合实践技术

、 第一n入门基础【理论讲解与案 1、Python环境搭建&#xff08; 下载、安装与版本选择&#xff09;。 2、如何选择Python编辑器&#xff1f;&#xff08;IDLE、Notepad、PyCharm、Jupyter…&#xff09; 3、Python基础&#xff08;数据类型和变量、字符串和编码、list和tu…

每日学术速递2.24

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.LG 1.BUAA_BIGSCity: Spatial-Temporal Graph Neural Network for Wind Power Forecasting in Baidu KDD CUP 2022 标题&#xff1a;BUAA_BIGSCity&#xff1a;百度KDD CUP 2022风电预测…

新C++(10):Map\Set的封装

"湖人总冠军"一、Map\Set的介绍Set是C标准库中的一种关联容器。所谓关联容器就是通过键&#xff08;key&#xff09;来读取和修改元素。与map关联容器不同&#xff0c;它只是单纯键的集合。取自这里Map是STL 的一个关联容器&#xff0c;它提供一对一&#xff08;其中…

《分布式技术原理与算法解析》学习笔记Day21

分布式数据存储三要素 什么是分布式数据存储系统&#xff1f; 分布式存储系统的核心逻辑&#xff0c;就是将用户需要存储的数据根据某种规则存储到不同的机器上&#xff0c;当用户想要获取指定数据时&#xff0c;再按照规则到存储数据的机器中获取。 分布式存储系统的三要素…

【多线程与高并发】- 浅谈volatile

浅谈volatile简介JMM概述volatile的特性1、可见性举个例子总结2、无法保证原子性举个例子分析使用volatile对原子性测试使用锁的机制总结3、禁止指令重排什么是指令重排序重排序怎么提高执行速度重排序的问题所在volatile禁止指令重排序内存屏障(Memory Barrier)作用volatile内…

PHY设备驱动

1. 概述 MAC控制器的驱动使用的是platform总线的连接方式&#xff0c;PHY设备驱动是基于device、driver、bus的连接方式。 其驱动涉及如下几个重要部分&#xff1a; 总线 - sturct mii_bus (mii stand for media independent interface) 设备 - struct phy_device 驱动 - struc…

Java学习笔记——时间日期类

目录概述时间日期类——Date构造方法Date类的常用方法simpledateformate类练习&#xff1a;秒杀活动概述 时间日期类——Date构造方法 Date类的常用方法 package top.xxx.www.date;import java.util.Date;public class DateDemo {public static void main(String[] args) {Date…

LabVIEW如何调用.m脚本LabVIEW调用MATLAB

LabVIEW如何调用.m脚本LabVIEW调用MATLAB有一个用MATLAB编写的脚本&#xff0c;想知道从LabVIEW调用它的方法&#xff0c;以及哪一个是最快的。解决方法有几种方法可以在LabVIEW中调用.m脚本。LabVIEW中的MATLABScript Node使用ActiveX调用MATLAB运行时系统。注意&#xff1a;不…

Linux内核网络协议栈套接字缓冲区原理

概念 Linux网络协议栈是内核中最大的组件之一&#xff0c;由于网络部分应用的范围很广&#xff0c;也相对较热&#xff0c;该部分现有的资料很多&#xff0c;学起来也比较容易。首先&#xff0c;我们看看贯穿网络协议栈各层的一个最关键数据结构——套接字缓冲区&#xff08;s…

python-pycharm爬虫工程(一)-依赖包下载部分

1,创建一个工程所需的python依赖包 2,依赖包下载慢或者无法下载解决 3,国内对应的镜像有哪些 1,创建一个工程所需的python依赖包 python新工程创建新的python依赖虚拟环境 File-->Settings-->Project:pc 其中pc是我的工程名 点击ok之后得到新的虚拟python依赖包…

【GlobalMapper精品教程】054:标签(标注)功能案例详解

同ArcGIS标注一样,globalmapper提供了动态标注的功能,称为标签,本文详解标签的使用方法。 文章目录 一、标签配置二、创建标签图层三、标签图层选项1. 标签字段2. 标签样式3. 标签格式4. 标签语言5. 标签优先级一、标签配置 在配置页面的【矢量显示】→标签选项卡下,有标签…

Springboot 整合Flowable工作流框架搭建

我们在开发自动化办公软件时经常会遇到各种审批流程功能&#xff0c;这个使用就需要使用到工作流引擎。目前主流的工作流引擎有Activiti、Flowable、camunda&#xff0c;其中Flowable是在Activiti的基础上开发出来的&#xff0c;基于BPMN2.0协议&#xff0c;它包括 BPMN&#x…