Spec-Zone.ru › Qt 5.14

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

Окружение JavaScript, предоставляемое QML, может выполнять допустимые стандартные конструкции JavaScript, такие как условные операторы, массивы, присвоение переменных и циклы. В дополнение к стандартным свойствам JavaScript, объект QML Global Object включает ряд вспомогательных методов, упрощающих создание пользовательских интерфейсов и взаимодействие с окружением 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, имеет обработчик касаний и метку Text. Обработчик касаний испускает сигнал 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 вызывается всякий раз, когда обработчик касаний испускает сигнал 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 в качестве аргумента. Например, следующий код подключает сигнал TapHandler's tapped к функции 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() вызывается всякий раз, когда сигнал TapHandler's tapped испускается.

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

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.14/qtqml-javascript-expressions.html

Spec-Zone.ru

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