Сигналы в QML

Последнее обновление: 06.01.2024

QML имеет механизм сигналов и обработчиков, аналогичный сигналам и слотам. Типы QML также могут определять сигналы, которые еще называются событиями. Для обработки события для сигнала определяется обработчик в виде свойства. Обработчик определяет действия, выполняемые при генерации сигнала. Причем сигнал и свойство-обработчик определяются в одном и том же классе. сигналу осуществуляется через специальное свойство. Обычно между наименованиями сигналов и свойств-обработчиков существует связь: свойство называется по имени сигнала + приставка on ("clicked" - "onClicked"). Например, простеший код приложения на QML:

import QtQuick
import QtQuick.Controls

Window {
    width: 250
    height: 200
    visible: true
    title: "METANIT.COM"

    Column{
        padding: 5

        Button{
            text: "Click Me"
            onClicked:  {
                header.text = "Button clicked!"
            }
        }
        Text {
            id: header
            font.pixelSize: 18
        }
    }
}

Для кнопок определен сигнал clicked, который генерируется при нажатии на кнопку. Чтобы установить обработчик этого сигнала, у типа Button определено свойство onClicked. В данном случае обработчик представляет блок кода, где устанавливается текст элемента header. То есть по нажатию на кнопку генерируется сигнал clicked, обработчик onClicked получит этот сигнал и будет выполняться:

Сигналы в Qt и QML

Действия обработчика события можно вынести в отдельную функцию JavaScript:

import QtQuick
import QtQuick.Controls

Window {
    width: 250
    height: 200
    visible: true
    title: "METANIT.COM"

    function setText(){
        header.text = "Signal clicked"
    }
    Column{
        padding: 5

        Button{
            text: "Click Me"
            onClicked: setText()
        }
        Text {
            id: header
            font.pixelSize: 18
        }
    }
}

В данном случае в качестве обработчика применяется функция setText.

Определение сигнала в QML

При необходимости мы можем сами определять свои сигналы в элементах QML. Для добавления сигнала внутри элемента QML применяется ключевое слово signal:

signal имя_сигнала[([параметр_1, параметр_2, ... параметр_N)]

После слова signal идет имя сигнала, затем в скобках перечисление параметров через запятую. Для каждого параметра указывается тип и имя. Если сигнал не принимает параметров, то указываются пустые скобки. Например:

import QtQuick
import QtQuick.Controls

Window {
    width: 250
    height: 200
    visible: true
    title: "METANIT.COM"

    Rectangle {
        id: rect
        signal sendMessage()    // определяем сигнал
        anchors.fill: parent
        Column{
            anchors.fill: parent
            Button {
                id:sendButton
                text: "Send"
                onClicked: rect.sendMessage()
            }
            Text{
                id: content
            }
        }
        onSendMessage: {    // определяем обработчик сигнала sendMessage()
            content.text += "SendMessage Signal Received\n"
        }
    }
}

Здесь для элемента Rectangle определен сигнал sendMessage

signal sendMessage()

Этот сигнал не имеет никаких параметров. Для обработки этого сигнала определен обработчик onSendMessage:

 onSendMessage: {    // определяем обработчик сигнала sendMessage()
    content.text += "SendMessage Signal Received\n"
}

В этом обработчике просто изменяем текст элемента content. Обратите внимание на соответствие по имени между сигналом и обработчиком.

Теперь нам надо сгенерировать сигнал. Для этого у элемента Button определен следующий обработчик onClicked:

onClicked: rect.sendMessage()

То есть по нажатию на кнопку генерируется сигнал sendMessage, который затем обрабатывается обработчиком onSendMessage.

Определение и вызов сигналов в Qt и QML

Если сигнал должен принимать какие-то параметры, то для его обработки можно определить функцию JavaScript, которая будет принимать соответствующий параметр:

import QtQuick
import QtQuick.Controls

Window {
    width: 250
    height: 200
    visible: true
    title: "METANIT.COM"

    function printMessage(message){
        content.text += message + "\n"
    }
    Rectangle {
        id: rect
        signal sendMessage(string message)    // определяем сигнал
        anchors.fill: parent
        Column{
            anchors.fill: parent
            Button {
                id:sendButton
                text: "Send"
                onClicked: rect.sendMessage("Hello World")
            }
            Text{
                id: content
            }
        }
        Component.onCompleted: {
            rect.sendMessage.connect(printMessage)
        }
    }
}

Здесь сигнал sendMessage принимает один параметр - message, который представляет строку - отправляемое сообщение.

signal sendMessage(string message)

Для обработки сигнала определяем функцию printMessage, которая по сигнатуре соответствует сигналу - принимает один параметр и которая выводит полученное через параметр сообщение в текстовое поле.

function printMessage(message){
    content.text += message + "\n"
}

Далее чтобы связать функцию с сигналом, у сигнала вызывается функция connect, в которую передается имя функции:

Component.onCompleted: {
    rect.sendMessage.connect(printMessage)
}

В зависимости от конкретного приложения место установки связи между функцией и сигналом может отличаться. В данном случае это производится в функции Component.onCompleted, которая вызывается при завершении инициализации компонентам.

Сигнал по прежнему генерируется в обработчике onClicked кнопки

onClicked: rect.sendMessage("Hello World")

только теперь в сигнал передается строка, которую получит функция printMessage через параметр message:

Связь сигналов и функций в Qt и QML

Подключение сигнала к другому сигналу

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

import QtQuick
import QtQuick.Controls

Window {
    width: 250
    height: 200
    visible: true
    title: "METANIT.COM"

    function printMessage(){            // обработчик сигнала
        content.text += "Hello World\n"
    }
    Rectangle {
        id: rect
        signal sendMessage()    // определяем сигнал
        anchors.fill: parent

        Column{
            anchors.fill: parent
            Button {
                id: sendButton
                text: "Send"
            }
            Text{
                id: content
            }
        }
        Component.onCompleted: {
            rect.sendMessage.connect(printMessage)
            sendButton.clicked.connect(sendMessage)
        }
    }
}

Здесь при возникновении сигнала clicked кнопки (по нажатию на кнопку) генерируется сигнал sendMessage

sendButton.clicked.connect(sendMessage)

А при генерации сигнала sendMessage вызывается функция printMessage.

rect.sendMessage.connect(printMessage)

Стоит отметить, что в данном случае сигнатура обоих сигналов - clicked и sendMessage совпадает.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850