草庐IT

QML学习十二:QML与C++交互之QML端发送信号绑定C++端

殷忆枫 2023-04-09 原文

若该文为原创文章,转载请注明原文出处

通过自定义Object类,可以在QML直接访问。通过这种方式,读取数据和设置数据都可以在C++端实现,QML端只需获取数据展示就行。

那QML端和C++端的信号和槽是如何使用的呢?

一、补充知识点

如何在QML端调用C++端的函数。正常情况下,在QML端调用C++函数,是无法调用的,但想要调用其他也很简单,只需要在C++端声明函数时添加Q_INVOKABLE,就可以被QML访问了。

比如在c++端定义一个func()函数,为了让QML可以调用,那就这样定义:

Q_INVOKABLE void func();

例子:

工程是以上一个工程为模板直接添加测试:

1、添加func()函数

myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <QtQml>


class MyObject : public QObject
{
    Q_OBJECT

//    QML_ELEMENT

    Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged)
    Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)

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

    static MyObject *getInstance();

    Q_INVOKABLE void func();

    int iValue() const;
    void setIValue( int newIValue);

    QString sString() const;
    void setSString(const QString &newSString);

private:
    int m_iValue;
    QString m_sString;

signals:
    void iValueChanged();
    void sStringChanged();


};

#endif // MYOBJECT_H

myobject.cpp

#include "myobject.h"

MyObject::MyObject(QObject *parent) : QObject(parent)
{
}

MyObject *MyObject::getInstance()
{
    static MyObject *obj = new MyObject();

    return obj;
}

int MyObject::iValue() const
{
    return m_iValue;
}

void MyObject::setIValue(int newIValue)
{
    if(newIValue == m_iValue)
        return ;
    m_iValue = newIValue;
    emit iValueChanged();
}

QString MyObject::sString() const
{
    return m_sString;
}

void MyObject::setSString(const QString &newSString)
{
    if(m_sString == newSString)
        return ;
    m_sString = newSString;
    emit sStringChanged();
}

void MyObject::func()
{
    qDebug() << __FUNCTION__;
}

fun()函数功能只是打印了下Log, 简单的测试。

2、QML访问func()函数

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

import MyObj 1.0


Window {
    id: window
    visible: true
    width: SCREEN_WIDTH
    height: 480
    title: qsTr("Hello World")

    Button {
        onClicked: {
            myobj.func();
        }
    }

    MyObject {
        id: myobj
    }
}

编译运行后,点击按钮将打印Log,说明有调用func()函数。

二、信号与槽

通过上面例子,QML可以访问C++的函数,那么QML发出的信号,C++端要如何接收呢?

也就是要如何连接信号与槽,这里有几种方式:

一、定义信号

在qml下定义要发送的信号: 

二、接收信号

在C++端定义接收的信号

 

三、连接方式

1、通过Connections连接

通过Connection来连接,类似于是访问函数,调用正常。

2、通过.connect连接

 3、通过C++端绑定

通过rootObjects连接,必须在engine加载完成后,load以后

三、完整代码

 1、main.cpp

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

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    app.setOrganizationName("myApp");

    QQmlApplicationEngine engine;
    QQmlContext *context = engine.rootContext();
    context->setContextProperty("SCREEN_WIDTH", 800);

//    MyObject obj;
//    context->setContextProperty("MyObject", &obj);

//    context->setContextProperty("MyObject", MyObject::getInstance());

    qmlRegisterType<MyObject>("MyObj", 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);

    // engine 加载完成后 load以后
    auto list = engine.rootObjects();
    auto window = list.first();
    QObject::connect(window, SIGNAL(qmlSig(int, QString)),
                     MyObject::getInstance(), SLOT(cppSlot(int, QString)));

    return app.exec();
}

2、myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <QtQml>


class MyObject : public QObject
{
    Q_OBJECT

//    QML_ELEMENT

    Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged)
    Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)

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

    static MyObject *getInstance();

    Q_INVOKABLE void func();

    int iValue() const;
    void setIValue( int newIValue);

    QString sString() const;
    void setSString(const QString &newSString);

public slots:
    void cppSlot(int i, QString s);

private:
    int m_iValue;
    QString m_sString;

signals:
    void iValueChanged();
    void sStringChanged();


};

#endif // MYOBJECT_H

3、myobject.cpp

#include "myobject.h"

MyObject::MyObject(QObject *parent) : QObject(parent)
{
}

MyObject *MyObject::getInstance()
{
    static MyObject *obj = new MyObject();

    return obj;
}

int MyObject::iValue() const
{
    return m_iValue;
}

void MyObject::setIValue(int newIValue)
{
    if(newIValue == m_iValue)
        return ;
    m_iValue = newIValue;
    emit iValueChanged();
}

QString MyObject::sString() const
{
    return m_sString;
}

void MyObject::setSString(const QString &newSString)
{
    if(m_sString == newSString)
        return ;
    m_sString = newSString;
    emit sStringChanged();
}

void MyObject::cppSlot(int i, QString s)
{
    qDebug() << __FUNCTION__ << "  " << i << "  " << s;
}

void MyObject::func()
{
    qDebug() << __FUNCTION__;
}

4、main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

import MyObj 1.0


Window {
    id: window
    visible: true
    width: SCREEN_WIDTH
    height: 480
    objectName: window
    title: qsTr("Hello World")

    signal qmlSig(int i, string s)

    Button {
        onClicked: {
            qmlSig(10, "lisi")
        }
    }

    MyObject {
        id: myobj
    }

//    Connections {
//        target: window
//        function onQmlSig(i, s) {
//            myobj.cppSlot(i, s)
//        }
//    }

//    Component.onCompleted: {
//        qmlSig.connect(myobj.cppSlot)
//    }
}



5、结果

四、总结

如有侵权,请及时联系博主删除,VX:18750903063

有关QML学习十二:QML与C++交互之QML端发送信号绑定C++端的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  2. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  3. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  4. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  5. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  6. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  7. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  8. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  9. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  10. ruby - 我如何学习 ruby​​ 的正则表达式? - 2

    如何学习ruby​​的正则表达式?(对于假人) 最佳答案 http://www.rubular.com/在Ruby中使用正则表达式时是一个很棒的工具,因为它可以立即将结果可视化。 关于ruby-我如何学习ruby​​的正则表达式?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1881231/

随机推荐