Spec-Zone.ru › Qt 5.11

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

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

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

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

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

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

import QtQuick 2.0

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

    MouseArea {
        anchors.fill: parent
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

Обращаясь к документации MouseArea, вы можете увидеть, что сигнал clicked испускается с параметром с именем mouse, который является объектом MouseEvent, содержащим дополнительные сведения о событии нажатия мыши. Это имя можно использовать в нашем обработчике onClicked, чтобы получить доступ к этому параметру. Например, тип MouseEvent имеет координаты x и y, которые позволяют нам вывести точное место, где была нажата мышь:

import QtQuick 2.0

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

    MouseArea {
        anchors.fill: parent
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);

            // access 'mouse' parameter
            console.log("Clicked mouse at", mouse.x, mouse.y)
        }
    }
}

Обработчики сигналов изменения свойств

Сигнал автоматически испускается при изменении значения свойства QML. Этот тип сигнала — сигнал изменения свойства, и обработчики сигналов для этих сигналов записываются в форме on<Property>Changed, где <Property> — это имя свойства, первая буква которого заглавная.

Например, тип MouseArea имеет свойство pressed. Чтобы получать уведомления всякий раз, когда это свойство изменяется, напишите обработчик сигнала с именем onPressedChanged.

import QtQuick 2.0

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

    MouseArea {
        anchors.fill: parent
        onPressedChanged: {
            console.log("Mouse area is pressed?", pressed)
        }
    }
}

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

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

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

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

import QtQuick 2.0

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

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Connections {
        target: mouseArea
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

Прикреплённые обработчики сигналов

Прикреплённый обработчик сигнала — это обработчик сигнала, который получает сигнал от типа присоединения, а не от объекта, в котором объявлен обработчик.

Например, Component.onCompleted — это прикреплённый обработчик сигнала. Этот обработчик часто используется для выполнения некоторого JavaScript-кода, когда процесс его создания завершен, как показано в примере ниже:

import QtQuick 2.0

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 сигнал типа Rectangle. Вместо этого объект типа Component тип присоединения со сигналом completed автоматически прикреплён к объекту Rectangle движком QML, и движок испускает этот сигнал при полном создании объекта, тем самым вызывая обработчик сигнала Component.onCompleted.

Прикреплённые обработчики сигналов позволяют объектам получать уведомления о конкретных сигналах, важных для каждого отдельного объекта. Если бы не было Component.onCompleted прикреплённого обработчика сигнала, например, то объект не мог бы получить это уведомление без регистрации на какой-то специальный сигнал от какого-то специального объекта. Механизм прикреплённых обработчиков сигналов позволяет объектам получать конкретные сигналы без этих дополнительных процессов.

Дополнительную информацию о прикреплённых обработчиках сигналов см. в разделе Прикреплённые свойства и прикреплённые обработчики сигналов.

Добавление сигналов к настраиваемым типам QML

Сигналы могут быть добавлены к настраиваемым типам QML с помощью ключевого слова signal.

Синтаксис определения нового сигнала:

signal <name>[([<type> <parameter name>[, ...]])]

Сигнал испускается путём вызова сигнала как метода.

Например, предположим, что код ниже определен в файле с именем SquareButton.qml. У корневого объекта Rectangle есть сигнал activated. Когда дочерний объект MouseArea нажимается, он испускает сигнал родителя activated с координатами нажатия мыши:

// SquareButton.qml
Rectangle {
    id: root

    signal activated(real xPosition, real yPosition)

    property int side: 100
    width: side; height: side

    MouseArea {
        anchors.fill: parent
        onPressed: root.activated(mouse.x, mouse.y)
    }
}

Теперь любые объекты типа SquareButton могут подключиться к сигналу activated с помощью обработчика сигнала onActivated.

// myapplication.qml
SquareButton {
    onActivated: console.log("Activated at " + xPosition + "," + yPosition)
}

Дополнительную информацию о написании сигналов для настраиваемых типов QML см. в разделе Атрибуты сигнала.

Подключение сигналов к методам и сигналам

Объекты сигналов имеют метод connect() для подключения сигнала к методу или другому сигналу. Когда сигнал подключается к методу, метод автоматически вызывается при каждом испускании сигнала. Этот механизм позволяет сигналу быть полученным методом вместо обработчика сигнала.

Ниже сигнал messageReceived подключается к трём методам с помощью метода connect().

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() может формировать различные цепочки сигналов.

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

    signal send()
    onSend: console.log("Send clicked")

    MouseArea {
        id: mousearea
        anchors.fill: parent
        onClicked: console.log("MouseArea clicked")
    }

    Component.onCompleted: {
        mousearea.clicked.connect(send)
    }
}

Всякий раз, когда испускается сигнал clicked MouseArea, сигнал send также будет автоматически испускаться.

output:
    MouseArea clicked
    Send clicked

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/qtqml-syntax-signals.html

Spec-Zone.ru

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