如何从 QML 收听 C++ 信号?

Ros*_*ers 4 c++ qt qt-creator qml

我有我称之为 C++“服务”的东西,我想向 QML 公开它的接口。我正在尝试使用QQmlContext'ssetContextProperty将对象链接到 QML 并从QML连接到它Connections

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

qrc:/main.qml:13: ReferenceError: service is not defined
Run Code Online (Sandbox Code Playgroud)

所以,QMLservice现在似乎找到了对象,但是 QML 插槽 javascript 函数没有被调用。我在 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
Run Code Online (Sandbox Code Playgroud)

应该有一条In onClbk消息,console.log("In onClbk"); 我知道我可以使用QMetaObject::invokeMethod直接调用 QML 对象的函数,但我试图通过使用信号和槽来实现更松散的耦合。

我想避免创建一个 QQuickItem如果可能的话,在 QML 中和实例化服务。

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

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

主程序

qrc:/main.qml:13: ReferenceError: service is not defined
Run Code Online (Sandbox Code Playgroud)

服务.h

class Service : public QQuickItem {
    Q_OBJECT

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

主文件

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");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

主界面文件

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"
    }
}
Run Code Online (Sandbox Code Playgroud)

cma*_*t85 6

您正在尝试将 JS 函数分配给cblk信号处理程序,这将不起作用,因为信号处理程序处理信号的函数。所以Connections块应该是:

Connections {
    target: service
    onClbk: {
        console.log("In onClbk");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不,JS 函数是第一类对象,因此您正在创建一个函数对象,该对象在信号处理程序超出范围时立即被销毁。信号处理程序接收它们发送的任何参数,因此如果您将信号定义为 `void clbk( double hello )`,信号处理程序将在其作用域内有一个可用的 `hello` var _但处理程序定义不会改变_。 (3认同)