Документация
ОС Аврора 5.1.5

Интеграция C++ и QML

Нативные приложения для ОС Аврора пишутся с помощью Qt 5.6. При этом интерфейс приложений создаётся средствами QML, а работа с данными может быть организована с помощью C++. Таким образом, нередко необходимо передавать данные между C++ и QML-частями приложения. Для этого можно зарегистрировать QML-тип на основе C++ класса.

Расширение C++-класса

Для создания C++-класса, доступного из QML нужно:

  1. Унаследовать его от QObject либо любого другого наследника QObject. Например, визуальные элементы наследуются от QQuickItem.
  2. Добавить макрос Q_OBJECT в описание класса.
  3. Зарегистрировать свойства, доступные из QML, с помощью макроса Q_PROPERTY.
  4. Зарегистрировать методы, доступные из QML, с помощью макроса Q_INVOKABLE. Или следует поместить метод в секцию public slots.

Пример C++-класса, не включённого в систему объектов Qt:

#ifndef VALUESTORAGE_H
#define VALUESTORAGE_H

class ValueStorage
{
    public:
        explicit ValueStorage(QObject *parent = nullptr);

        int value() const;

        void setValue(int value);
        void resetValue();

    private:
        int m_value;
};

Пример расширения этого класса с доступом к свойству и методам из QML:

#ifndef VALUESTORAGE_H
#define VALUESTORAGE_H

#include <QObject>

class ValueStorage : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)

    public:
        explicit ValueStorage(QObject *parent = nullptr);

        int value() const;
        
        Q_INVOKABLE void resetValue();

    public slots:
        void setValue(int value);

    signals:
        void valueChanged();

    private:
        int m_value;
};

В примере экспортируется свойство value и методы resetValue и valueChanged.

Пример основан на учебных материалах о разработке под ОС Аврора.

Подробнее о макросах можно узнать в документации Qt.

Реализация объявленного класса в cpp-файле:

#include "valuestorage.h"
#include <QDebug>

ValueStorage::ValueStorage(QObject *parent) :
    QObject(parent),
    m_value(0)
{ }

int ValueStorage::value() const
{
    return m_value;
}

void ValueStorage::setValue(int value)
{
    if (m_value == value)
        return;
    m_value = value;
    emit valueChanged();
}

void ValueStorage::resetValue()
{
    setValue(0);
}

Регистрация QML-типа

После того как класс расширен, его можно регистрировать как QML-тип. Для этого в main.cpp следует выполнить следующие действия:

  1. Подключить класс посредством директивы #include: #include "valuestorage.h".
  2. Зарегистрировать QML-тип в функции main с помощью метода qmlRegisterType: qmlRegisterType<ValueStorage>("ru.auroraos.Counter", 1, 0, "ValueStorage");. При этом следует придумать имя QML-модуля, в котором будет находиться новый тип (ru.auroraos.Counter в примере), его версию и имя QML-типа (ValueStorage). Имя QML-модуля должно соответствовать требованиям валидатора. Имя QML-компонента может совпадать с именем C++-класса. Оно не должно совпадать с именами компонентов из Qt Quick и QML-плагинов, чтобы не было конфликта имён.

Полный пример кода:

#include <auroraapp.h>
#include <QtQuick>
#include "valuestorage.h"

int main(int argc, char *argv[])
{
    QScopedPointer<QGuiApplication> application(Aurora::Application::application(argc, argv));
    application->setOrganizationName(QStringLiteral("ru.auroraos"));
    application->setApplicationName(QStringLiteral("Counter"));

    qmlRegisterType<ValueStorage>("ru.auroraos.Counter", 1, 0, "ValueStorage");

    QScopedPointer<QQuickView> view(Aurora::Application::createView());
    view->setSource(Aurora::Application::pathTo(QStringLiteral("qml/Counter.qml")));
    view->show();

    return application->exec();
}

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

Зарегистрированный QML-тип можно импортировать в QML по имени модуля:

import ru.auroraos.Counter 1.0

Затем можно создать QML-объект:

ValueStorage {
    id: valueStorage
}

У объекта можно получить значение свойства value:

Text {
    text: "Value: %1".arg(valueStorage.value)
    ...
}

Или изменить его:

onClicked: valueStorage.value++

Объекту можно добавить обработчик сигнала:

ValueStorage {
    id: valueStorage
    onValueChanged: console.log(value)
}

Можно вызвать метод:

onClicked: valueStorage.resetValue()

Полный пример кода:

import QtQuick 2.0
import ru.auroraos.Counter 1.0

Item {
    id: root
    objectName: "Counter"

    property real fontSize: width / 16

    ValueStorage {
        id: valueStorage
        objectName: "valueStorage"
        onValueChanged: console.log(value)
    }

    Column {
        objectName: "layout"
        width: parent.width

        Text {
            id: valueText
            objectName: "valueText"
            text: "Value: %1".arg(valueStorage.value)
            height: root.height / 3
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: fontSize
            anchors.horizontalCenter: parent.horizontalCenter
        }

        Row {
            objectName: "buttonsRow"
            height: root.height - valueText.height

            MouseArea {
                width: root.width / 2
                height: parent.height

                Text {
                    text: "Increment"
                    anchors.centerIn: parent
                    font.pixelSize: fontSize
                }

                onClicked: valueStorage.value++
            }

            MouseArea {
                width: root.width / 2
                height: parent.height

                Text {
                    text: "Reset"
                    anchors.centerIn: parent
                    font.pixelSize: fontSize
                }

                onClicked: valueStorage.resetValue()
            }
        }
    }
}

Мы используем cookies для персонализации сайта и его более удобного использования. Вы можете запретить cookies в настройках браузера.

Пожалуйста ознакомьтесь с политикой использования cookies.