问题
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 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
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
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.
I would like to avoid creating a QQuickItem
and instantiating the service in the QML, if at all possible.
Unfortunately, the boilerplate code is legion and this is my 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"
}
}
回答1:
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");
}
}
回答2:
You should explicitly use the type of service, like Service or QObject (not auto). It's good for you to ensure what you want the object do.
No need define additional function in SLOT of your QML, because it self is a function. In the case if you want to use parameter, do like this:
signals: void clbk(QString signalString); Connections { target: service onClbk: { console.log(signalString); } }
Notice that you must use exact name of parameters, and the type of params must be register using qRegisterMetaType.
来源:https://stackoverflow.com/questions/29995250/how-can-i-listen-to-a-c-signal-from-qml