Spec-Zone.ru › Qt 6.0

Система сигналов и обработчиков событий

Компоненты приложения и пользовательского интерфейса должны взаимодействовать друг с другом. Например, кнопка должна знать, что пользователь нажал на неё. Кнопка может изменить цвет, чтобы указать своё состояние, или выполнить некоторую логику. Также, приложение должно знать, нажимает ли пользователь на кнопку. Приложение может передать это событие нажатия другим приложениям.

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. Движок испускает этот сигнал, когда объект Прямоугольник создается, тем самым вызывая обработчик сигнала 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(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

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.0/qtqml-syntax-signals.html

Spec-Zone.ru

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