Spec-Zone.ru › Qt 5.13

JavaScript-выражения в документах QML

Окружение JavaScript, предоставляемое QML, может выполнять допустимые стандартные конструкции JavaScript, такие как условные операторы, массивы, присвоение переменных и циклы. Помимо стандартных свойств JavaScript, глобальный объект QML включает ряд вспомогательных методов, которые упрощают построение пользовательских интерфейсов и взаимодействие с окружением QML.

Окружение JavaScript, предоставляемое QML, более строгое, чем в веб-браузере. Например, в QML нельзя добавлять или изменять члены глобального объекта JavaScript. В обычном JavaScript это можно сделать случайно, используя переменную без её объявления. В QML это вызовет исключение, поэтому все локальные переменные должны быть явно объявлены. Полное описание ограничений кода JavaScript, выполняемого из QML, см. в разделе Ограничения среды JavaScript.

Различные части документов QML могут содержать код JavaScript:

  1. Тело связей свойств. Эти выражения JavaScript описывают отношения между свойствами QML-объекта свойств. При изменении зависимостей свойства оно также автоматически обновляется в соответствии с указанными отношениями.
  2. Тело обработчиков сигналов. Эти инструкции JavaScript автоматически оцениваются всякий раз, когда QML-объект излучает связанный сигнал.
  3. Определение пользовательских методов. Функции JavaScript, определённые внутри тела QML-объекта, становятся методами этого объекта.
  4. Отдельные файлы ресурсов JavaScript (.js). Эти файлы фактически отделены от документов QML, но их можно импортировать в документы QML. Функции и переменные, определённые в импортированных файлах, могут использоваться в связях свойств, обработчиках сигналов и пользовательских методах.

JavaScript в связях свойств

В следующем примере свойство color прямоугольника зависит от свойства pressed обработчика нажатий. Это отношение описывается с помощью условного выражения:

import QtQuick 2.12

Rectangle {
    id: colorbutton
    width: 200; height: 80;

    color: inputHandler.pressed ? "steelblue" : "lightsteelblue"

    TapHandler {
        id: inputHandler
    }
}

Фактически, в определении связи свойства можно использовать любое выражение JavaScript (независимо от сложности), если результат выражения является значением, тип которого может быть присвоен свойству. Это включает побочные эффекты. Однако сложные связи и побочные эффекты не рекомендуются, так как они могут снизить производительность, читаемость и поддерживаемость кода.

Существует два способа определения связи свойства: наиболее распространённый показан в примере выше, в инициализации свойства. Второй (и гораздо более редкий) способ — присвоить свойству функцию, возвращаемую из функции Qt.binding(), внутри императивного кода JavaScript, как показано ниже:

import QtQuick 2.12

Rectangle {
    id: colorbutton
    width: 200; height: 80;

    color: "red"

    TapHandler {
        id: inputHandler
    }

    Component.onCompleted: {
        color = Qt.binding(function() { return inputHandler.pressed ? "steelblue" : "lightsteelblue" });
    }
}

Дополнительную информацию о том, как определять связи свойств, см. в документации по связям свойств, а о различиях между присвоением значений и связями свойств см. в документации Присвоение свойства по сравнению с связью свойства.

JavaScript в обработчиках сигналов

Типы QML-объектов могут излучать сигналы в ответ на определённые события. Эти сигналы могут обрабатываться функциями-обработчиками сигналов, которые клиенты могут определять для реализации пользовательской логики программы.

Предположим, что кнопка, представленная типом Rectangle, имеет TapHandler и метку Text. TapHandler излучает сигнал tapped, когда пользователь нажимает на кнопку. Клиенты могут реагировать на сигнал в обработчике onTapped с использованием выражений JavaScript. Движок QML выполняет эти выражения JavaScript, определённые в обработчике по мере необходимости. Как правило, обработчик сигнала связан с выражениями JavaScript для инициирования других событий или присвоения значений свойств.

import QtQuick 2.12

Rectangle {
    id: button
    width: 200; height: 80; color: "lightsteelblue"

    TapHandler {
        id: inputHandler
        onTapped: {
            // arbitrary JavaScript expression
            console.log("Tapped!")
        }
    }

    Text {
        id: label
        anchors.centerIn: parent
        text: inputHandler.pressed ? "Pressed!" : "Press here!"
    }
}

Дополнительную информацию о сигналах и обработчиках сигналов см. в следующих разделах:

  • Система сигналов и событий обработчиков
  • Атрибуты QML-объектов

JavaScript в автономных функциях

Логика программы также может быть определена в функциях JavaScript. Эти функции могут быть определены непосредственно в документах QML (как пользовательские методы) или внешне в импортированных файлах JavaScript.

JavaScript в пользовательских методах

Пользовательские методы могут быть определены в документах QML и могут вызываться из обработчиков сигналов, связей свойств или функций в других QML-объектах. Такие методы часто называют встроенными функциями JavaScript, потому что их реализация включена в определение типа QML-объекта (документ QML), а не во внешнем файле JavaScript.

Пример встроенного пользовательского метода:

import QtQuick 2.12

Item {
    function fibonacci(n){
        var arr = [0, 1];
        for (var i = 2; i < n + 1; i++)
            arr.push(arr[i - 2] + arr[i -1]);

        return arr;
    }
    TapHandler {
        onTapped: console.log(fibonacci(10))
    }
}

Функция fibonacci выполняется всякий раз, когда TapHandler излучает сигнал tapped.

Примечание: Пользовательские методы, определённые непосредственно в документе QML, доступны другим объектам, поэтому встроенные функции в корневом объекте QML-компонента могут вызываться вызывающими сторонами за пределами компонента. Если этого не требуется, метод можно добавить к объекту, не являющемуся корневым, или, лучше всего, написать во внешнем файле JavaScript.

Дополнительную информацию о определении пользовательских методов в QML с помощью JavaScript см. в документации Атрибуты QML-объектов.

Функции, определённые в файле JavaScript

Нетривиальная логика программы лучше всего отделяется в отдельный файл JavaScript. Этот файл можно импортировать в QML с помощью инструкции import, подобно QML модулям.

Например, метод fibonacci() в предыдущем примере можно переместить во внешний файл под названием fib.js и получить доступ к нему следующим образом:

import QtQuick 2.12
import "fib.js" as MathFunctions

Item {
    TapHandler {
        onTapped: console.log(MathFunctions.fibonacci(10))
    }
}

Дополнительную информацию о загрузке внешних файлов JavaScript в QML см. в разделе Импортирование ресурсов JavaScript в QML.

Подключение сигналов к функциям JavaScript

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

Сигнал, излучаемый QML-объектом, может быть подключён к функции JavaScript, вызвав метод сигнала connect() и передав функцию JavaScript в качестве аргумента. Например, следующий код подключает сигнал tapped TapHandler к методу jsFunction() в script.js:

import QtQuick 2.12
import "script.js" as MyScript

Item {
    id: item
    width: 200; height: 200

    TapHandler {
        id: inputHandler
    }

    Component.onCompleted: {
        inputHandler.tapped.connect(MyScript.jsFunction)
    }
}
// script.js

function jsFunction() {
    console.log("Called JavaScript function!")
}

Метод jsFunction() вызывается всякий раз, когда сигнал tapped TapHandler излучается.

Дополнительную информацию см. в разделе Подключение сигналов к методам и сигналам.

JavaScript в коде запуска приложения

Иногда необходимо запустить некоторый императивный код при запуске приложения (или экземпляра компонента). Хотя может показаться заманчивым просто включить скрипт запуска в виде глобального кода во внешний файл скрипта, это может иметь серьёзные ограничения, поскольку QML-окружение может не быть полностью установлено. Например, некоторые объекты могут не быть созданы, или некоторые связи свойств могут не быть установлены. Точные ограничения кода глобальных скриптов см. в разделе Ограничения среды JavaScript.

QML-объект излучает сигнал Component.completed attached при завершении его инициализации. Код JavaScript в соответствующем обработчике Component.onCompleted выполняется после инициализации объекта. Таким образом, лучшим местом для написания кода запуска приложения является обработчик Component.onCompleted верхнего уровня объекта, потому что этот объект излучает сигнал Component.completed при полном установлении QML-окружения.

Например:

import QtQuick 2.0

Rectangle {
    function startupFunction() {
        // ... startup code
    }

    Component.onCompleted: startupFunction();
}

Любой объект в файле QML — включая вложенные объекты и вложенные QML-компоненты — может использовать это присоединённое свойство. Если для выполнения при запуске существует более одного обработчика onCompleted(), они выполняются последовательно в неопределённом порядке.

Аналогично, каждый Component излучает сигнал destruction() непосредственно перед уничтожением.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/qtqml-javascript-expressions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API