Как передавать сигналы из javascript в qml

Я хочу испускать сигнал из javascript-файла и получать его в qml-файле (чтобы узнать, когда завершится трудоемкая операция).

Как мне это сделать?


person aleks_misyuk    schedule 02.01.2012    source источник


Ответы (3)


Ни решения Алекса, ни решения Раджи на самом деле не отвечают на вопрос. Метод 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
person Peace Makes Plenty    schedule 14.09.2013
comment
Я согласен. Хорошее решение. - person aleks_misyuk; 04.10.2013

Спасибо, @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();
...
person aleks_misyuk    schedule 02.01.2012
comment
не имеет отношения к вопросу, но он вошел в систему, а не вошел в систему;) - person Kamil Klimek; 03.01.2012
comment
Прошу прощения за мой английский. Я обещаю пойти на языковой курс в этом месяце. - person aleks_misyuk; 03.01.2012

Ну, очень хакерски вызывать сигналы из реального JS-файла. Но есть вариант получше, ИМХО, сам его использовал. Создайте свой собственный класс.

MyClass.qml

import QtQuick 2.0

QtObject
{
    property var myVariable
    function myFunction() { console.log("emitting signal"); mySignal() }
    signal mySignal
}

Таким образом, вы можете легко добиться необходимой инкапсуляции. И можно даже красиво подключиться к объекту.

Затем вы можете делать с ним все, что хотите: создать из него синглтон, создать глобальный объект, создать его экземпляр.

person marmistrz    schedule 11.09.2015