Система сигналов и обработчиков событий
Компоненты приложения и пользовательского интерфейса должны взаимодействовать друг с другом. Например, кнопка должна знать, что пользователь нажал на нее. Кнопка может изменить цвет, чтобы указать свое состояние, или выполнить какой-либо логический код. Также приложение должно знать, нажимает ли пользователь на кнопку. Приложение может потребоваться передать это событие нажатия на другие приложения.
QML имеет механизм сигналов и обработчиков, где сигнал — это событие, а на сигнал реагируют через обработчик сигнала. Когда испускается сигнал, вызывается соответствующий обработчик сигнала. Размещение логики, такой как скрипт или другие операции, в обработчике позволяет компоненту реагировать на событие.
Получение сигналов с помощью обработчиков сигналов
Чтобы получать уведомления при испускании определенного сигнала для определенного объекта, определение объекта должно объявлять обработчик сигнала, названный on<Signal>, где <Signal> — имя сигнала с заглавной первой буквой. Обработчик сигнала должен содержать JavaScript-код, который будет выполняться при вызове обработчика сигнала.
Например, тип Кнопки из модуля Qt Quick Controls имеет сигнал clicked, который испускается всякий раз, когда нажимается кнопка. В этом случае обработчик сигнала для получения этого сигнала должен быть onClicked. В примере ниже, всякий раз, когда нажимается кнопка, вызывается обработчик onClicked, применяющий случайный цвет к родительскому Прямоугольнику:
import QtQuick
import QtQuick.Controls
Rectangle {
id: rect
width: 250; height: 250
Button {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "Change color!"
onClicked: {
rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
}
}
} Обработчики сигналов изменения свойств
Сигнал автоматически испускается, когда значение свойства QML изменяется. Этот тип сигнала — сигнал изменения свойства, а обработчики сигналов для этих сигналов записываются в виде on<Property>Changed, где <Property> — имя свойства с заглавной первой буквой.
Например, тип MouseArea имеет свойство pressed. Чтобы получать уведомления всякий раз, когда это свойство изменяется, напишите обработчик сигнала, названный onPressedChanged:
import QtQuick
Rectangle {
id: rect
width: 100; height: 100
TapHandler {
onPressedChanged: console.log("taphandler pressed?", pressed)
}
} Несмотря на то, что документация TapHandler не документирует обработчик сигнала, названный onPressedChanged, сигнал неявно предоставляется тем, что свойство pressed существует.
Использование типа Connections
В некоторых случаях может быть желательно получить доступ к сигналу за пределами объекта, который его испускает. Для этих целей модуль QtQuick предоставляет тип Connections для подключения к сигналам произвольных объектов. Объект Connections может получать любой сигнал от указанного им target.
Например, обработчик onClicked в предыдущем примере мог быть получен корневым Прямоугольником вместо этого, разместив обработчик onClicked в объекте Connections, который имеет свой target, установленный на button:
import QtQuick
import QtQuick.Controls
Rectangle {
id: rect
width: 250; height: 250
Button {
id: button
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "Change color!"
}
Connections {
target: button
function onClicked() {
rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
}
}
} Прикрепленные обработчики сигналов
Прикрепленный обработчик сигнала получает сигнал от прикрепленного типа, а не от объекта, в котором объявлен обработчик.
Например, Component.onCompleted — это прикрепленный обработчик сигнала. Он часто используется для выполнения некоторого JavaScript-кода, когда завершен процесс его создания. Вот пример:
import QtQuick
Rectangle {
width: 200; height: 200
color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1)
Component.onCompleted: {
console.log("The rectangle's color is", color)
}
} Обработчик onCompleted не реагирует на сигнал completed от типа Прямоугольник. Вместо этого объект типа Component прикрепляемого типа со сигналом completed был автоматически прикреплен к объекту Прямоугольник движком QML. Движок испускает этот сигнал при создании объекта Rectangle, тем самым вызывая обработчик сигнала Component.onCompleted.
Прикрепленные обработчики сигналов позволяют объектам получать уведомления о конкретных сигналах, которые важны для каждого отдельного объекта. Если бы не было Component.onCompleted прикрепленного обработчика сигнала, например, объект не мог бы получить это уведомление без регистрации на какой-либо специальный сигнал от какого-либо специального объекта. Механизм прикрепленного обработчика сигнала позволяет объектам получать определенные сигналы без дополнительного кода.
См. Прикрепленные свойства и прикрепленные обработчики сигналов для получения дополнительной информации о прикрепленных обработчиках сигналов.
Добавление сигналов к пользовательским типам QML
Сигналы могут быть добавлены к пользовательским типам QML с помощью ключевого слова signal.
Синтаксис определения нового сигнала:
signal <name>[([<type> <parameter name>[, ...]])]
Сигнал испускается путем вызова сигнала как метода.
Например, код ниже определен в файле, названном SquareButton.qml. Корневой объект Прямоугольник имеет сигнал activated, который испускается всякий раз, когда дочерний TapHandler tapped. В этом конкретном примере сигнал activated испускается с координатами x и y щелчка мыши:
// SquareButton.qml
import QtQuick
Rectangle {
id: root
signal activated(real xPosition, real yPosition)
property point mouseXY
property int side: 100
width: side; height: side
TapHandler {
id: handler
onTapped: root.activated(root.mouseXY.x, root.mouseXY.y)
onPressedChanged: root.mouseXY = handler.point.position
}
} Теперь любой объект типа SquareButton может подключиться к сигналу activated с помощью обработчика сигнала onActivated:
// myapplication.qml
SquareButton {
onActivated: (xPosition, yPosition)=> console.log("Activated at " + xPosition + "," + yPosition)
} См. Атрибуты сигнала для получения более подробной информации о написании сигналов для пользовательских типов QML.
Подключение сигналов к методам и сигналам
Объекты сигналов имеют метод connect() для подключения сигнала к методу или другому сигналу. Когда сигнал подключен к методу, метод автоматически вызывается всякий раз, когда испускается сигнал. Этот механизм позволяет сигналу быть полученным методом вместо обработчика сигнала.
Ниже сигнал messageReceived подключен к трем методам с помощью метода connect():
import QtQuick
Rectangle {
id: relay
signal messageReceived(string person, string notice)
Component.onCompleted: {
relay.messageReceived.connect(sendToPost)
relay.messageReceived.connect(sendToTelegraph)
relay.messageReceived.connect(sendToEmail)
relay.messageReceived("Tom", "Happy Birthday")
}
function sendToPost(person, notice) {
console.log("Sending to post: " + person + ", " + notice)
}
function sendToTelegraph(person, notice) {
console.log("Sending to telegraph: " + person + ", " + notice)
}
function sendToEmail(person, notice) {
console.log("Sending to email: " + person + ", " + notice)
}
} Во многих случаях достаточно получать сигналы через обработчики сигналов, а не использовать функцию connect(). Однако использование метода connect позволяет сигналу быть полученным несколькими методами, как показано ранее, что невозможно с обработчиками сигналов, так как они должны иметь уникальные имена. Также метод connect полезен при подключении сигналов к динамически созданным объектам.
Существует соответствующий метод disconnect() для удаления подключенных сигналов:
Rectangle {
id: relay
//...
function removeTelegraphSignal() {
relay.messageReceived.disconnect(sendToTelegraph)
}
} Подключение сигнала к сигналу
Подключая сигналы к другим сигналам, метод connect() может формировать различные цепочки сигналов.
import QtQuick
Rectangle {
id: forwarder
width: 100; height: 100
signal send()
onSend: console.log("Send clicked")
TapHandler {
id: mousearea
anchors.fill: parent
onTapped: console.log("Mouse clicked")
}
Component.onCompleted: {
mousearea.tapped.connect(send)
}
} Всякий раз, когда сигнал tapped TapHandler испускается, сигнал send также будет автоматически испускаться.
output:
MouseArea clicked
Send clicked
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qtqml-syntax-signals.html