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

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

通过自定义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

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷忆枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值