Определение свойств в коде C++ и их связь с QML

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

На уровне класса C++ также можно определить свойства, к которым можно будет установить привязку в коде QML. Благодаря механизму сигналов приложение получит уведомление о том, что изменилось значение свойства класса и обновит все привязанные свойства других элементов.

Для создания свойства в коде C++ применяется макрос Q_PROPERTY, который имеет следующий синтаксис:

Q_PROPERTY(тип_свойства имя_свойства READ метод_получения WRITE метод_изменения NOTIFY сигнал_изменения)

Определение свойства состоит из ряда компонентов. Вначале указывается тип и имя свойства. Затем после слова READ указывается метод, который возвращает значение свойства. После слова WRITE указывается метод, который изменяет значение свойства. В конце после слова NOTIFY указывается сигнал, который генерируется при изменении значения свойства.

Например, пусть в проекте определен класс Counter, код которого состоит из заголовочного файла counter.h и файла с реализацией counter.cpp:

Определение свойств в классах С++ в Qt и QML

В заголовочном файле counter.h определим следующий код:

#ifndef COUNTER_H
#define COUNTER_H

#include <QObject>

class Counter: public QObject
{
    Q_OBJECT
    Q_PROPERTY(int count READ getValue WRITE setValue
                   NOTIFY valueChanged)
public:
    Counter(QObject *parent = nullptr){}

    int getValue() const;
    void setValue(int newValue);
    Q_INVOKABLE void decrease();
    Q_INVOKABLE void increase();
signals:
    void valueChanged(int);
private:
    int value{};
};

#endif // COUNTER_H

Класс Counter наследуется от QObject и применяет макрос Q_OBJECT, благодаря чему класс может определять сигналы.

Далее идет макрос Q_PROPERTY, который указывает, что определяется свойство, которое называется "count" и имеет тип int. Для чтения этого свойства предназначен метод getValue, а для изменения его значения - метод setValue, в который передается новое значение. Для уведомления системы об изменении значения свойства применяется сигнал valueChanged.

В классе определено приватное свойство value, в котором хранится некоторое значение объекта Counter. Также в дополнение к методам getValue()/setValue() определено два метода - increase и decrease, которые будут изменять значение value. Благодаря макросу Q_INVOKABLE эти методы можно вызывать из кода QML.

В файле counter.cpp определим реализацию методов:

#include "counter.h"

void Counter::increase()
{
    setValue(value+1);
}

void Counter::decrease()
{
    if(value > 0) setValue(value-1);
}
int Counter::getValue() const
{
    return value;
}
void Counter::setValue(int newValue)
{
    value = newValue;
    emit valueChanged(value);
}

Методы increase и decrease, вызывают метод setValue, который увеличиваетт или уменьшает значение value на 1 и генерирует сигнал valueChanged, передавая в него обновленное значение.

В файле main.cpp зарегистрируем тип Counter:

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "counter.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    // регистрация типа Counter
    qmlRegisterType<Counter>("counter", 1, 0,"Counter");

    const QUrl url("qrc:/path/main.qml");
    engine.load(url);
    return app.exec();
}

Используем тип Counter в файле main.qml:

import QtQuick
import QtQuick.Controls
import counter

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

    Counter{ id: counter}
    Row{
        spacing: 10
        anchors.centerIn: parent
        Button {
            text: "+"
            width: 30
            height: 30
            onClicked: counter.increase()
        }
        Text{
            text: counter.count
        }
        Button {
            text: "-"
            width: 30
            height: 30
            onClicked: counter.decrease()
        }
    }
}

Здесь определен элемент Counter с идентификатором counter, с которым будут взаимодействовать другие элементы. В частности, здесь также определены две кнопки, по нажатию на которые будут вызываться методы increase и decrease объекта counter.

Для вывода значения свойства count определен элемент Text, текст которого привязан к свойству count:

Text{
    text: counter.count
}

При этом нам не надо устанавливать явным образом обработчик сигнала valueChanged для объекта Counter. При изменении значения value в Counter система получит соответствующее увеломление и автоматически изменит привязанное свойство - свойство text элемента Text

Q_PROPERTY и привязка свойств классов  C++ к элементами в QML в Qt

Причем нам не надо явным образом вызывать методы increase/decrease или даже setValue для изменения поля value. Мы можем напрямую присвоить свойству count новое значение:

import QtQuick
import QtQuick.Controls
import counter

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

    Counter{ id: counter}
    Row{
        anchors.centerIn: parent
        Button {
            text: "+"
            width: 30
            height: 30
            onClicked: counter.count+=5
        }
        Text{
            text: counter.count
        }
        Button {
            text: "-"
            width: 30
            height: 30
            onClicked: counter.count-=5
        }
    }
}

Здесь не вызывается явным образом никаких методов класса Counter, мы работаем со свойством count, как с обычным полем класса:

onClicked: counter.count += 5

Однако поскольку при определении свойства в классе Counter мы указали в качестве метода изменения метод setValue, то при любых присвоениях свойству count любых значений будет неявно вызываться метод setValue, в который через параметр будет передаваться присваиваемое свойству значение.

Равным образом, когда мы получаем значение свойства count:

text: counter.count

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

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