Система событий сигналов и обработчиков
Компоненты приложения и пользовательского интерфейса должны обмениваться данными. Например, кнопка должна знать, что пользователь нажал на неё. Кнопка может изменить цвет, чтобы указать своё состояние, или выполнить определённый код. Также приложение должно знать, нажимает ли пользователь на кнопку. Приложение может передать это событие нажатия на другие приложения.
QML имеет механизм сигналов и обработчиков, где сигнал — это событие, а на сигнал реагирует обработчик сигнала. При отправке сигнала вызывается соответствующий обработчик сигнала. Размещение логики, такой как скрипт или другие операции, в обработчике позволяет компоненту реагировать на событие.
Получение сигналов с помощью обработчиков сигналов
Чтобы получать уведомления при отправке определённого сигнала для определённого объекта, определение объекта должно объявлять обработчик сигнала с именем on<Сигнал>, где <Сигнал> — это имя сигнала, первая буква которого заглавная. Обработчик сигнала должен содержать JavaScript-код, который будет выполняться при вызове обработчика сигнала.
Например, тип Кнопка из модуля Qt Quick Controls имеет сигнал clicked, который отправляется всякий раз, когда нажимается кнопка. В этом случае обработчик сигнала для получения этого сигнала должен быть onClicked. В примере ниже, всякий раз, когда нажимается кнопка, вызывается обработчик onClicked, применяющий случайный цвет к родительскому Прямоугольнику:
import QtQuick 2.13
import QtQuick.Controls 2.13
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<Свойство>Changed, где <Свойство> — это имя свойства, первая буква которого заглавная.
Например, тип MouseArea имеет свойство pressed. Чтобы получать уведомления всякий раз, когда это свойство изменяется, напишите обработчик сигнала с именем onPressedChanged:
import QtQuick 2.13
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 2.13
import QtQuick.Controls 2.13
Rectangle {
id: rect
width: 250; height: 250
Button {
id: button
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "Change color!"
}
Connections {
target: button
onClicked: {
rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
}
}
} Присоединенные обработчики сигналов
Присоединённый обработчик сигнала получает сигнал от присоединяемого типа, а не от объекта, в котором объявлен обработчик.
Например, Component.onCompleted — это присоединённый обработчик сигнала. Он часто используется для выполнения некоторого JavaScript-кода, когда завершается процесс его создания. Вот пример:
import QtQuick 2.13
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. Движок отправляет этот сигнал, когда объект Прямоугольник создаётся, тем самым вызывая обработчик сигнала Component.onCompleted.
Присоединённые обработчики сигналов позволяют объектам получать уведомления о конкретных сигналах, которые важны для каждого отдельного объекта. Если бы не было Component.onCompleted присоединённого обработчика сигнала, например, объект не мог бы получить это уведомление без регистрации на какой-то специальный сигнал от какого-то специального объекта. Механизм присоединённых обработчиков сигналов позволяет объектам получать конкретные сигналы без дополнительного кода.
Дополнительную информацию о присоединённых обработчиках сигналов см. в разделе Присоединенные свойства и присоединенные обработчики сигналов.
Добавление сигналов к пользовательским типам QML
Сигналы можно добавить к пользовательским типам QML с помощью ключевого слова signal.
Синтаксис определения нового сигнала:
signal <name>[([<type> <parameter name>[, ...]])]
Сигнал отправляется, вызывая сигнал как метод.
Например, код ниже определён в файле с именем SquareButton.qml. Корневой объект Прямоугольник имеет сигнал activated, который отправляется всякий раз, когда дочерний TapHandler tapped. В этом конкретном примере сигнал activated отправляется с координатами x и y щелчка мыши:
// SquareButton.qml
import QtQuick 2.13
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(mouseXY.x, mouseXY.y)
onPressedChanged: mouseXY = handler.point.position
}
} Теперь любые объекты типа SquareButton могут подключиться к сигналу activated с помощью обработчика сигнала onActivated:
// myapplication.qml
SquareButton {
onActivated: console.log("Activated at " + xPosition + "," + yPosition)
} Дополнительные сведения о написании сигналов для пользовательских типов QML см. в разделе Атрибуты сигналов.
Подключение сигналов к методам и сигналам
Объекты сигналов имеют метод connect() для подключения сигнала либо к методу, либо к другому сигналу. При подключении сигнала к методу метод автоматически вызывается при отправке сигнала. Этот механизм позволяет получать сигнал методом вместо обработчика сигнала.
Ниже сигнал messageReceived подключается к трём методам с помощью метода connect():
import QtQuick 2.13
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 2.13
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-5.13/qtqml-syntax-signals.html