JavaScript-выражения в документах QML
Окружение JavaScript, предоставляемое QML, может выполнять допустимые стандартные конструкции JavaScript, такие как условные операторы, массивы, присваивание переменных и циклы. В дополнение к стандартным свойствам JavaScript, объект QML Global Object включает в себя ряд вспомогательных методов, упрощающих создание пользовательских интерфейсов и взаимодействие с окружением QML.
Окружение JavaScript, предоставляемое QML, более строгое, чем в веб-браузере. Например, в QML нельзя добавлять или изменять члены объекта глобального JavaScript. В обычном JavaScript это можно сделать случайно, используя переменную без объявления. В QML это вызовет исключение, поэтому все локальные переменные должны быть явно объявлены. Подробное описание ограничений кода JavaScript, выполняемого из QML, см. в разделе Ограничения окружения JavaScript.
Различные части документов QML могут содержать код JavaScript:
- Тело связей свойств. Эти выражения JavaScript описывают взаимосвязь между свойствами QML-объектов свойств. При изменении любой из зависимостей свойства, оно также автоматически обновляется в соответствии с заданной взаимосвязью.
- Тело обработчиков сигналов. Эти операторы JavaScript автоматически вычисляются всякий раз, когда QML-объект излучает связанный сигнал.
- Определение пользовательских методов. JavaScript-функции, определенные внутри тела QML-объекта, становятся методами этого объекта.
- Самостоятельные файлы ресурсов JavaScript (.js). Эти файлы фактически отделены от документов QML, но могут быть импортированы в документы QML. Функции и переменные, определенные в импортированных файлах, могут быть использованы в связях свойств, обработчиках сигналов и пользовательских методах.
JavaScript в связях свойств
В следующем примере 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" });
}
} Дополнительную информацию о том, как определять связи свойств, см. в документации по связям свойств, а информацию о том, чем связи отличаются от присваивания значений, см. в документации по присваиванию свойств по сравнению со связями свойств.
JavaScript в обработчиках сигналов
Типы 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 в автономных функциях
Логика программы также может быть определена в JavaScript-функциях. Эти функции могут быть определены встроены в документы QML (как пользовательские методы) или внешне в импортированных файлах JavaScript.
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-функцию в качестве аргумента. Например, следующий код подключает сигнал clicked MouseArea к функции 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.
См. Подключение сигналов к методам и сигналам для получения дополнительной информации.
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/archives/qt-5.6/qtqml-javascript-expressions.html