我想从 javascript-file 发出信号并在 qml-file 中接收它(查找耗时操作何时完成)。
我该怎么做?
Alex 和 Raja 的解决方案都没有真正回答这个问题。Alex 在于直接从 javascript 代码调用 QML slot 方法,而 Raja 在于从 Javascript 代码设置 QML 对象的属性值。这两种方法都否定了信号/槽机制的主要优点,即信令对象不需要知道槽。
这篇博文(不是我的)描述了一种更接近信号/槽机制精神的方法。它包括在 javascript 文件中创建一个 QML 对象(通过Qt.createQmlObject()
函数),该对象的唯一功能是包含 javascript 的对象信号。通过调用内部 QML 对象信号(例如internalQmlObject.signalName()
)从 javascript 发出信号,并且 javascript 对象信号可以在 QML 中使用通常的connect
机制通过javascriptObject.internalQmlObject.signalName.connect(receiver.slotName)
.
改编自博客文章的示例如下:
javascript_object.js:
var internalQmlObject = Qt.createQmlObject('import QtQuick 2.0; QtObject { signal someSignal(int value) }', Qt.application, 'InternalQmlObject');
function doSomething() {
internalQmlObject.someSignal(42);
}
测试.qml:
import QtQuick 2.0
import 'javascript_object.js' as JavascriptObject
Rectangle {
Rectangle {
id: someComponent
function someSlot(v) {
console.log("Signal received " + v);
}
}
Component.onCompleted: {
JavascriptObject.internalQmlObject.someSignal.connect(someComponent.someSlot);
JavascriptObject.doSomething();
}
}
在执行时,它给出以下信息:
% qmlscene test.qml
Signal received 42
谢谢你,@RajaVarma。
我为自己找到了解决方案。
在qml-file 中:创建元素 Item(我的 loginItem),其中包含扮演插槽角色的函数。例如(我需要知道什么时候处理登录事件):
import "scripts/auth.js" as Auth
...
Item {
id: loginItem
// Send himself to javascript module named Auth
Component.onCompleted: {
Auth.setLoginItem(loginItem);
}
// "Slot" function
function logged() {
console.debug("Login successfully");
// Do something
...
}
}
在js-file 中:为 loginItem 创建接收器并使用它。
var loginItem;
function setLoginItem(tempLoginItem) {
loginItem = tempLoginItem;
}
...
// Emit "signal"
loginItem.logged();
...
好吧,从一个真实的 JS 文件中调用信号是非常hacky的。但是有一个更好的选择,恕我直言,我自己使用它。创建自己的班级。
MyClass.qml
import QtQuick 2.0
QtObject
{
property var myVariable
function myFunction() { console.log("emitting signal"); mySignal() }
signal mySignal
}
这样您就可以轻松实现所需的封装。你甚至可以很好地连接到对象。
然后你可以用它做任何你想做的事情:从它创建一个单例,创建一个全局对象,实例化它。