如何从 QML 收听 C++ 信号? [英] How can I listen to a C++ signal from QML?

查看:39
本文介绍了如何从 QML 收听 C++ 信号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 C++服务",我想向 QML 公开它的接口.我正在尝试使用 QQmlContextsetContextProperty 将对象链接到 QML 并从 QML Connections.

I have what I'm calling a C++ "service" who's interface I want to expose to QML. I'm trying to use QQmlContext's setContextProperty to link the object into the QML and connect to it from a QML Connections block.

QML 不会像以前那样在我没有在 QML 上下文中注册服务时抱怨引用错误:

QML isn't complaining with a reference error as it did previously when I hadn't registered the service in the QML context:

qrc:/main.qml:13: ReferenceError: service is not defined

所以,QML 现在似乎找到了 service 对象,但是 QML 插槽 javascript 函数没有被调用.我在 Qt Creator 中看到了这一点:

So, QML seems to find the service object now, however the QML slot javascript function is not getting invoked. I see this in Qt Creator:

Debugging starts
QML debugging is enabled. Only use this in a safe environment.
QML Debugger: Waiting for connection on port 62301...
Calling the clbk signal
Debugging has finished

每个 console.log("In onClbk"); 应该有一个 In onClbk 消息;我知道我可以使用 QMetaObject::invokeMethod 调用 QML 对象的直接函数,但我试图通过使用信号和插槽来降低耦合.

There should be an In onClbk message per console.log("In onClbk"); I know that I can use QMetaObject::invokeMethod to invoke a QML object's function directly, but I am trying to have a little looser coupling through the use of signals and slots.

如果可能,我想避免创建 QQuickItem 并在 QML 中实例化服务.

I would like to avoid creating a QQuickItem and instantiating the service in the QML, if at all possible.

不幸的是,样板代码很多,这是我的SSCCE.

这是通过 Qt Creator 创建的所有项目目录的 zip 文件5.4.

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    auto rc = engine.rootContext();
    auto service = new Service();
    engine.rootContext()->setContextProperty(QStringLiteral("service"), service);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    // invoke the trigger arbitrarily
    QTimer *timer = new QTimer();
    timer->setSingleShot(true);
    QObject::connect(timer, SIGNAL(timeout()), service, SLOT(trigger_clbk()));
    timer->start(4000);
    return app.exec();
}

service.h

class Service : public QQuickItem {
    Q_OBJECT

public:
    virtual ~Service(){}
signals:
    void clbk();
public slots:
    void trigger_clbk() {
        qDebug()<<"Calling the clbk signal";
        clbk();
    }
};

main.qml

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    visible: true
    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            Qt.quit();
        }
        // subscribe to a signal
        Connections {
            target: service
            onClbk: function(){
                console.log("In onClbk");
            }
        }
    }
}

Main.ui.qml

import QtQuick 2.3

Rectangle {
    property alias mouseArea: mouseArea

    width: 360
    height: 360

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Text {
        anchors.centerIn: parent
        text: "Hello World"
    }
}

推荐答案

您正在尝试将一个 JS 函数分配给 cblk 信号处理程序,它不会作为信号处理程序工作 处理信号的函数.所以 Connections 块应该是:

You're trying to assign a JS function to the cblk signal handler, that's not going to work as the signal handler is the function that handles the signal. So the Connections block should read:

Connections {
    target: service
    onClbk: {
        console.log("In onClbk");
    }
}

这篇关于如何从 QML 收听 C++ 信号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆