如何收听来自 QML 的 C++ 信号?
How can I listen to a C++ signal from QML?
我有所谓的 C++ "service" 我想向 QML 公开的接口。我正在尝试使用 QQmlContext
's setContextProperty
to link the object into the QML and connect to it from a QML Connections
block.
当我没有在 QML 上下文中注册服务时,QML 没有像以前那样抱怨引用错误:
qrc:/main.qml:13: ReferenceError: service is not defined
所以,QML 现在似乎找到了 service
对象,但是 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
每个 console.log("In onClbk");
应该有一个 In onClbk
消息我知道我可以使用 QMetaObject::invokeMethod
直接调用 QML 对象的函数,但我试图有一点松散的耦合通过使用信号和槽。
如果可能的话,我想避免在 QML 中创建 QQuickItem
和实例化服务。
不幸的是,样板代码很多,这是我的SSCCE。
Here is a zip file of all the project directory as created through Qt Creator 5.4.
main.cpp
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
块应该是:
Connections {
target: service
onClbk: {
console.log("In onClbk");
}
}
您应该明确使用服务类型,例如 Service 或 QObject(不是自动)。确保您希望对象做什么对您有好处。
不需要在QML的SLOT中定义额外的函数,因为它本身就是一个函数。在这种情况下,如果你想使用参数,这样做:
signals:
void clbk(QString signalString);
Connections {
target: service
onClbk: {
console.log(signalString);
}
}
请注意,您必须使用准确的参数名称,并且必须使用 qRegisterMetaType 注册参数类型。
我有所谓的 C++ "service" 我想向 QML 公开的接口。我正在尝试使用 QQmlContext
's setContextProperty
to link the object into the QML and connect to it from a QML Connections
block.
当我没有在 QML 上下文中注册服务时,QML 没有像以前那样抱怨引用错误:
qrc:/main.qml:13: ReferenceError: service is not defined
所以,QML 现在似乎找到了 service
对象,但是 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
每个 console.log("In onClbk");
应该有一个 In onClbk
消息我知道我可以使用 QMetaObject::invokeMethod
直接调用 QML 对象的函数,但我试图有一点松散的耦合通过使用信号和槽。
如果可能的话,我想避免在 QML 中创建 QQuickItem
和实例化服务。
不幸的是,样板代码很多,这是我的SSCCE。
Here is a zip file of all the project directory as created through Qt Creator 5.4.
main.cpp
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
块应该是:
Connections {
target: service
onClbk: {
console.log("In onClbk");
}
}
您应该明确使用服务类型,例如 Service 或 QObject(不是自动)。确保您希望对象做什么对您有好处。
不需要在QML的SLOT中定义额外的函数,因为它本身就是一个函数。在这种情况下,如果你想使用参数,这样做:
signals: void clbk(QString signalString); Connections { target: service onClbk: { console.log(signalString); } }
请注意,您必须使用准确的参数名称,并且必须使用 qRegisterMetaType 注册参数类型。