Как излучать сигналы из JavaScript в QML - PullRequest
5 голосов
/ 02 января 2012

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

Как я могу это сделать?

Ответы [ 3 ]

7 голосов
/ 14 сентября 2013

Ни одно из решений Алекса Нора Раджа действительно не отвечает на вопрос. Алекс состоит в том, чтобы вызывать непосредственно из кода javascript метод слота QML, а раджа состоит в том, чтобы устанавливать значение свойства объекта 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
4 голосов
/ 03 января 2012

Спасибо, @ 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();
...
2 голосов
/ 11 сентября 2015

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

MyClass.qml

import QtQuick 2.0

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

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

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

...