Я хочу испускать сигнал из javascript-файла и получать его в qml-файле (чтобы узнать, когда завершится трудоемкая операция).
Как мне это сделать?
Я хочу испускать сигнал из javascript-файла и получать его в qml-файле (чтобы узнать, когда завершится трудоемкая операция).
Как мне это сделать?
Ни решения Алекса, ни решения Раджи на самом деле не отвечают на вопрос. Метод Alex заключается в вызове непосредственно из кода javascript метода слота QML, а метод Raja заключается в установке значения свойства объекта QML из кода Javascript. Оба подхода сводят на нет главное преимущество механизма сигнал/слот, заключающееся в том, что объекту сигнализации не нужно знать о слоте.
Подход, более близкий духу механизма сигнала/слота, описан в этом запись в блоге (не моя). Он состоит из файла javascript в создании объекта QML (через функцию Qt.createQmlObject()
), единственная функция которого состоит в том, чтобы содержать сигналы объекта javascript. Сигналы испускаются из javascript посредством вызова внутреннего сигнала объектов QML (например, internalQmlObject.signalName()
), а сигнал объекта javascript может быть подключен в QML к слотам 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);
}
test.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-файле: создать элемент 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-файле: создайте приемник для loginItem и используйте его.
var loginItem;
function setLoginItem(tempLoginItem) {
loginItem = tempLoginItem;
}
...
// Emit "signal"
loginItem.logged();
...
Ну, очень хакерски вызывать сигналы из реального JS-файла. Но есть вариант получше, ИМХО, сам его использовал. Создайте свой собственный класс.
MyClass.qml
import QtQuick 2.0
QtObject
{
property var myVariable
function myFunction() { console.log("emitting signal"); mySignal() }
signal mySignal
}
Таким образом, вы можете легко добиться необходимой инкапсуляции. И можно даже красиво подключиться к объекту.
Затем вы можете делать с ним все, что хотите: создать из него синглтон, создать глобальный объект, создать его экземпляр.