QML学习笔记【06】:QML与C++交互

news2024/11/14 3:57:43

1 QML端直接调用C++端变量及函数

1、 创建继承自QObject的C++类,对象必须继承自QObject才能在QML被使用和访问

2、在类定义中使用Q_PROPERTY导出成员的READ、WRITE、NOTIFY接口,这样类中的成员变量就可以在QML调用和修改了,同时变量被修改后也会发送信号通知QML端。用 Q_INVOKABLE 修饰成员函数,这样类中的成员函数就可以直接被QML调用。前提是该模块已经被注册过!!!

class MyObject : public QObject
{
    Q_OBJECT

public:
    explicit MyObject(QObject *parent = nullptr);
    ~MyObject();
    static MyObject * getInstance();

    //读取函数,对应READ
    int getIValue();
    QString getSStr();

    //被 Q_INVOKABLE 修饰C++函数能直接被QML调用
    Q_INVOKABLE void setCapture(bool state);

    //写函数,对应 WRITE,可以没有
    Q_INVOKABLE void setIValue(int value);
    Q_INVOKABLE void setSStr(const QString &str);

    //定义公有的槽函数
public slots:
    Q_INVOKABLE void cppSlot(int i, QString s);

private slots:
    void timer_timeout();

signals:
    //修改通知,对应 NOTIFY,可以没有。可以分开写,也可以用同一个信号
    void iValueChanged(int value);
    void sStrChanged(const QString &str);
    void myObjDataChanged();
    void cppSig(QVariant i, QVariant s);

private:
    QTimer *timer;
    int iValue;
    QString sStr;

    // property declarations required for QML
    Q_PROPERTY(int iValue READ getIValue WRITE setIValue NOTIFY myObjDataChanged)
    Q_PROPERTY(QString sStr READ getSStr WRITE setSStr NOTIFY myObjDataChanged)
};

3、注册模块

QQmlApplicationEngine engine;
//1、使用setContextProperty设置全局对象/上下文对象。作用域为全局
//常用于一些不变的常量
QQmlContext *context = engine.rootContext();
context->setContextProperty("SCREEN_WIDTH", 800);
//2、使用qmlRegisterType注册模块,在qml中通过 import 模块名称 进行引用
//模块名称、主版本号、次版本号、类名称
qmlRegisterType<MyObject>("MyObj11", 1, 0, "MyObject");

4、QML端调用

//创建MyObject对象
MyObject{
    objectName: "myobj"
    //可直接操作MyObject类中的数据了
    id: myobj
    iValue: 10
    sStr: "dhl"
    Component.onCompleted:{
        console.log(iValue, sStr)
    }
}
//监控myobj.iValue的改变
onValueChanged: {
    console.log("onValueChanged: ", value)
}

//1、直接访问C++的成员变量和成员函数....................................
Button{
    id: btn1
    objectName: "button1"
    x:20; y:20
    anchors.margins: 10
    text: "访问C++成员和方法"
    onClicked: {
        myobj.iValue += 2 //修改myobj.iValue的值
        onoff = onoff ? 0 : 1
        myobj.setCapture(onoff) //调用C++端函数
    }
}

2 QML端发送信号绑定C++端槽函数

可有两种方法可绑定QML端信号与C++端槽函数,分别在C++端绑定和在QML端绑定。需要注意的是:方式1实际是在QML信号的槽函数中调用的C++端槽函数,相当于是间接的绑定C++端的槽函数

//2、QML端发送信号绑定C++端槽函数....................................
signal qmlSig(int i, string s)
Button{
    id: btn2
    objectName: "button2"
    x:200; y:20
    anchors.margins: 10
    text: "QML端发送信号绑定C++端"
    onClicked: {
        qmlSig(1, "qml signal--->cpp slot") //发送信号
    }
}
//方式1:在QML中使用Connections连接
//    Connections {
//        target: root
//        onQmlSig:{  //QML信号为 qmlSig(int i, string s)
//            myobj.cppSlot(i, s)
//        }
//    }
//方式2:在QML中使用信号的connect方法
Component.onCompleted: {
    qmlSig.connect(myobj.cppSlot)
}
//方式3:在C++中绑定
//详见 main.cpp

3 C++端发送信号绑定QML端槽函数

可有两种方法可绑定C++端信号与QML端槽函数,分别在C++端绑定和在QML端绑定。需要注意的是:

1、QML中槽函数的参数类型对应c++端的必须都是QVariant!!!!

2、在C++端绑定的方式,经测试,在当前版本中不好使!

//3、C++端发送信号绑定QML端槽函数....................................
function qmlSlot(i, s){ //参数类型对应c++端的必须都是QVariant!!!!
    console.log("qmlslot: ", i, s)
}
//方式1:在QML中使用Connections连接
Connections{
    target: myobj
    onCppSig:{ //c++端信号为void cppSig(QVariant i, QVariant s),C++端发送该信号后,会执行qmlSlot函数
        qmlSlot(i, s)
    }
}
//方式2:在C++中绑定。经测试,此方式在当前版本中不好使!!!
//详见 main.cpp

4 C++端直接调用QML端函数

在C++端需要使用 QMetaObject::invokeMethod 方法来调用QML端函数

//4、C++端直接调用QML端函数....................................
function qmlFunc(i, s){
    return "qmlFunc success"
}
//详见 main.cpp

main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QVariant>
#include <QDebug>
#include "myobject.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    
    //=====》C++与QML数据交互
    //1、使用setContextProperty设置全局对象/上下文对象。作用域为全局
    //常用于一些不变的常量
    QQmlContext *context = engine.rootContext();
    context->setContextProperty("SCREEN_WIDTH", 800);
    //2、使用qmlRegisterType注册模块,在qml中通过 import 模块名称 进行引用
    //模块名称、主版本号、次版本号、类名称
    qmlRegisterType<MyObject>("MyObj11", 1, 0, "MyObject");

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    //=====》C++与QML信号槽绑定
    auto list = engine.rootObjects();
    auto window = list.first();
//    auto buttonObj = list.first()->findChild<QObject *>("button1");
    //绑定qml信号与c++槽
//    QObject::connect(window, SIGNAL(qmlSig(int,QString)),
//                     MyObject::getInstance(), SLOT(cppSlot(int,QString)));
    //绑定c++信号和qml槽
//    QObject::connect(MyObject::getInstance(), SIGNAL(cppSig(QVariant,QVariant)),
//                     window, SLOT(qmlSlot(QVariant, QVariant)));

    //=====》C++直接调用QML函数
    QVariant res;
    QVariant arg1 = 123;
    QVariant arg2 = "dhl";
    QMetaObject::invokeMethod(window, "qmlFunc",
                              Q_RETURN_ARG(QVariant,res),
                              Q_ARG(QVariant, arg1),
                              Q_ARG(QVariant, arg2));
    qDebug() <<"res=" << res;

    return app.exec();
}

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

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

相关文章

剑指 Offer 18. 删除链表的节点

一、题目描述 给定单向链表的头指针和一个要删除的节点的值&#xff0c;定义一个函数删除该节点。 返回删除后的链表的头节点。 示例 1: 输入: head [4,5,1,9], val 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点&#xff0c;那么在调用了你的函数之后&#xf…

2022年最后一篇推文 | C语言编程十诫

正文大家好&#xff0c;我是bug菌~2022年最后一篇推文原本选择一篇年终总结会比较合适&#xff0c;然而坐在窗台&#xff0c;望着窗外思索了良久&#xff0c;与往年总结有点不同&#xff0c;这个时间节点有着他的特殊性&#xff0c;不出意外&#xff0c;明年会有非常多的变化、…

OpenShift 4 - 用 HyperShift 实现以“托管集群”方式部署运行 OpenShift 集群

《OpenShift / RHEL / DevSecOps / Ansible 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.11 ACM 2.6 AWS 环境中验证 文章目录用 HyperShift 实现 OpenShift 托管集群什么是 HyperShift 托管集群以及架构HyperShift 托管集群的价值成本优势部署优势管理优势在 RHACM …

【Kaggle】Global Wheat Detection

代码链接 实验目的 小麦来自世界各地。密度的小麦植株经常重叠&#xff1b;风会使得照片模糊&#xff1b;外观会因成熟度&#xff0c;颜色&#xff0c;基因型和头部方向而异。使用图像处理和目标检测完成小麦头的位置的标定。完成训练并现场验证后上传指定的输出文件进行验证…

大数据NiFi(三):NiFi关键特性

文章目录 NiFi关键特性 一、​​​​​​​​​​​​​​流管理

人工智能轨道交通行业周刊-第28期(2022.12.26-2023.1.1)

本期关键词&#xff1a;NOCC、车站闸机、雾闪、2022年度盘点、智慧园区 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通Rai…

安全—01day

DNS 域名解析过程: 1.浏览器首先查询浏览器的缓存&#xff0c;因为浏览器会按照一定的频率缓存 DNS 记录 2.若浏览器无缓存&#xff0c;那么查询操作系统的 HOST 文件&#xff0c;查询是否有 DNS 记录。 3.若还没有命中域名&#xff0c;就请求本地域名服务器该服务器一般都会缓…

Qt音视频开发07-合并音视频文件

一、前言 之前已经把音视频分开存储了对应的文件&#xff0c;因为这个需求特别少&#xff0c;当然确实有部分用户是需要把音视频分开存储&#xff0c;但是毕竟是很少数&#xff0c;绝大部分的用户都是音视频合并到一个MP4文件&#xff0c;所以如果要合并到一个文件&#xff0c…

二进制与十六进制的相互转换;按位操作:与() 和 或(|)

目录 一、二进制转换十六进制 二、十六进制转换二进制 三、按位操作&#xff1a;与&#xff08;&&#xff09; 和 或&#xff08;|&#xff09; 1、按位与&#xff08;&&#xff09;操作 2、按位或&#xff08;|&#xff09;操作 得出结论&#xff1a;清0用与&am…

【金猿案例展】海尔集团——追光AI-AOI赋能PCBA缺陷检测

‍数之联案例本项目案例由数之联投递并参与“数据猿年度金猿策划活动——《2022大数据产业年度创新服务企业》榜单/奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业AOI&#xff08;Automated Optical Inspection缩写&#xff09;的中文全称是自动光学检测。通过…

className 还能这么用,你学会了吗

抛出问题 className大家都用过吧&#xff0c;用它在react项目中设置样式。它的用法很简单&#xff0c;除了可以设置一个样式外&#xff0c;react中也可以使用className引入多个类样式。 这次在写项目的时候&#xff0c;碰到一个非常小但是当时却一直解决不了的问题。后面在复…

python基础语法25-进程理论

一、简介 服务器为了能够同时为多个客户端服务,则需要能够同时处理多个网络连接的方法。python提供了3个主要的方法来实现这个目的,multiprocessing、threading和异步I/O。 今天主要说一下进程multiprocessing。 multiprocessing是一个和threading(多线程)类似的库,这个多…

【MVC和三层架构】联系、区别以及简单实践

MVC架构模式MVC架构模式概述引入MVCMVC和三层架构之间的联系和区别三层架构与MVC联系和区别银行转账小项目实践MVC架构模式概述 MVC架构模式是软件架构中的一个架构模式。 M&#xff08;Model&#xff1a;数据/业务&#xff09; V&#xff08;View&#xff1a;视图/展示&#x…

深入xJavaFxTool的插件开发模式

背景 时光华丽丽的来到了2023年&#xff0c;首先在这里祝大家新年快乐&#xff0c;希望大家在新的一年里都能心想事成&#xff0c;万事如意&#xff0c;最重要的是身体健康。过去的2022年里&#xff0c;大家一定都是收获满满。不论是技术的&#xff0c;家庭的&#xff0c;事业的…

【C++】map 与 set 的介绍与使用

目录 一、关联式容器 二、键值对 三、set 3.1 set 的介绍 3.2 set 的使用 3.3. set 的使用举例 四、map 4.1 map的介绍 3.2 map 的使用 4.3 map的使用举例 五、经典练习题 1.set的使用 2.map的使用 思路一(稳定排序)&#xff1a; 思路二(priority_queue)&#x…

LabVIEW使用共享变量在两台计算机之间进行通信

LabVIEW使用共享变量在两台计算机之间进行通信 需要选择一台计算机作为服务器并发布变量&#xff0c;而另一台计算机作为客户端接收变量。然后&#xff0c;按照以下步骤设置服务器和客户端计算机。 服务器机器&#xff1a; 创建LabVIEW项目并通过右键单击“我的电脑”并选择…

opencv-python常用函数解析及参数介绍(六)——图像梯度

图像梯度前言Sobel算子算子的定义Sobelx效果演示Sobely效果演示完整轮廓直接计算复杂图片的轮廓Scharr算子与laplacian算子scharr算子的定义laplacian算子定义三种算子的效果对比结尾前言 前面的文章中我们介绍了用膨胀和腐蚀得到了图像轮廓&#xff0c;图像梯度也是一种可以得…

五年六次

今天是 2022 年的最后一天&#xff0c;可算等来了。讽刺的是&#xff0c;就在昨天&#xff0c;小号写了篇文章&#xff0c;啥主题就不说了&#xff0c;然后晚上文章被删了&#xff0c;账号居然也被封了。2022 全年虽然我写过很多文章都被和谐了&#xff0c;但是最后一天喜提封号…

二、Django

Django 提示&#xff1a;本文根据b站黑马python课整理 链接指引 > 黑马程序员python企业级开发项目-手把手从0到1开发《美多商城》 文章目录DjangoMVT图解项目准备1.创建项目2.创建应用3.更换python解释器4.安装应用5.本地化6.项目中匹配urls7.应用中匹配urls.py8.准备视图…

Tensorflow游乐场 在线可视化

playground.tensorflow.org Tensorflow游乐场 Tensorflow游乐场提供了一个在线可视化AI训练。A Neural Network Playgroundhttp://playground.tensorflow.org/ Tensorflow游乐场 是干啥的呢 给一堆点分出蓝色部分和橙色部分。也就是二分类。 它提供了4种数据来训练 每种数据…