Spec-Zone.ru › Qt 6.1

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

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

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

Spec-Zone.ru

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