Spec-Zone.ru › Qt 5.11

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

Окружение JavaScript, предоставляемое QML, может выполнять допустимые стандартные конструкции JavaScript, такие как условные операторы, массивы, присвоение переменных, циклы. Помимо стандартных свойств JavaScript, объект QML Global содержит ряд вспомогательных методов, которые упрощают построение пользовательских интерфейсов и взаимодействие с окружением 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. Функции и переменные, определённые в импортированных файлах, можно использовать в связях свойств, обработчиках сигналов и пользовательских методах.

Яваскрипт в связях свойств

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

import QtQuick 2.0

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

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

    MouseArea {
        id: mousearea
        anchors.fill: parent
    }
}

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

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

import QtQuick 2.0

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

    color: "red"

    MouseArea {
        id: mousearea
        anchors.fill: parent
    }

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

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

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

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

Предположим, что кнопка, представленная типом Rectangle, имеет область MouseArea и метку Text. Область MouseArea будет генерировать свой сигнал pressed при нажатии пользователем определённой интерактивной области, что автоматически вызовет обработчик onPressed, который может быть определён клиентами. Движок QML выполнит выражения JavaScript, определённые в обработчиках onPressed и onReleased, по мере необходимости. Обычно обработчик сигнала связан с выражениями JavaScript для инициализации других событий или просто для присвоения значений свойств.

import QtQuick 2.0

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

    MouseArea {
        id: mousearea
        anchors.fill: parent

        onPressed: {
            // arbitrary JavaScript expression
            label.text = "I am Pressed!"
        }
        onReleased: {
            // arbitrary JavaScript expression
            label.text = "Click Me!"
        }

    }

    Text {
        id: label
        anchors.centerIn: parent
        text: "Press Me!"
    }
}

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

Яваскрипт в автономных функциях

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

Яваскрипт в пользовательских методах объекта

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

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

import QtQuick 2.0

Item {
    function factorial(a) {
        a = parseInt(a);
        if (a <= 0)
            return 1;
        else
            return a * factorial(a - 1);
    }

    MouseArea {
        anchors.fill: parent
        onClicked: console.log(factorial(10))
    }
}

Функция факториала будет выполняться всякий раз, когда область MouseArea обнаружит сигнал clicked.

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

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

Функции в импортированных файлах JavaScript

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

Например, метод factorial() в приведённом выше примере можно перенести во внешний файл с именем factorial.js, и получить доступ к нему так:

import "factorial.js" as MathFunctions

Item {
    MouseArea {
        anchors.fill: parent
        onClicked: console.log(MathFunctions.factorial(10))
    }
}

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

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

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

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

import QtQuick 2.0
import "script.js" as MyScript

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

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Component.onCompleted: {
        mouseArea.clicked.connect(MyScript.jsFunction)
    }
}
// script.js

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

Функция jsFunction() теперь будет вызываться всякий раз, когда генерируется сигнал clicked области MouseArea.

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

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

Иногда необходимо выполнить некоторый императивный код при запуске приложения (или экземпляра компонента). Хотя и заманчиво включить скрипт запуска как глобальный код во внешний файл скрипта, это может иметь серьёзные ограничения, так как среда 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/archives/qt-5.11/qtqml-javascript-expressions.html

Spec-Zone.ru

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