Spec-Zone.ru › Qt 6.1

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

Spec-Zone.ru

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