Spec-Zone.ru › Qt 5.12

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

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

QML имеет механизм сигналов и обработчиков, где сигнал — это событие, а на сигнал реагирует обработчик сигнала. При отправке сигнала вызывается соответствующий обработчик сигнала. Размещение логики, такой как скрипт или другие операции, в обработчике позволяет компоненту реагировать на событие.

Получение сигналов с помощью обработчиков сигналов

Чтобы получить уведомление при отправке определенного сигнала для определенного объекта, определение объекта должно объявить обработчик сигнала с именем on<Signal>, где <Signal> — имя сигнала с заглавной первой буквой. Обработчик сигнала должен содержать JavaScript-код, который будет выполняться при вызове обработчика сигнала.

Например, тип Кнопки из модуля Qt Quick Controls имеет сигнал clicked, который отправляется всякий раз, когда нажимается кнопка. В этом случае обработчик сигнала для получения этого сигнала должен быть onClicked. В примере ниже, всякий раз, когда нажимается кнопка, вызывается обработчик onClicked, применяющий случайный цвет к родительскому Прямоугольнику:

import QtQuick 2.12
import QtQuick.Controls 2.12

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.12

Rectangle {
    id: rect
    width: 100; height: 100

    TapHandler {
        onPressedChanged: console.log("taphandler pressed?", pressed)
    }
}

Хотя в документации TapHandler не описан обработчик сигнала с именем onPressedChanged, сигнал неявно предоставляется тем, что существует свойство pressed.

Использование типа Connections

В некоторых случаях может потребоваться получить доступ к сигналу вне объекта, который его отправляет. Для этих целей модуль QtQuick предоставляет тип Connections для подключения к сигналам произвольных объектов. Объект Connections может получать любой сигнал от указанного целевого объекта.

Например, обработчик onClicked в предыдущем примере мог быть получен корневым Прямоугольником вместо этого, разместив обработчик onClicked в объекте Connections, у которого свойство target установлено на button:

import QtQuick 2.12
import QtQuick.Controls 2.12

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.12

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 2.12

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.12

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.12

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

Spec-Zone.ru

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