Evgenii Legotckoi
05 липня 2017 р. 16:05

QML - Підручник 029. Реєстрація об'єкта Singleton для використання "статичних" методів у QML

Поняття статичних методів, які використовуються в QML, дещо відрізняється від класичного в C++, коли в класі створюються статичні методи, які можна використовувати звертаючись до імені класу, а не до якогось конкретного об'єкта. У випадку з QML справи трохи інакше. Для того, щоб використовувати такі методи в QML, які присутні в класі C++, необхідно зареєструвати Сінглетон об'єкт, який надаватиме потрібні методи, причому ці методи вже не повинні бути статичними самі по собі. Вони повинні бути як мінімум позначені макросом Q_INVOKABLE , щоб їх можна було використовувати в QML.

Для реєстрації Синглетону необхідно використовувати функцію qmlRegisterSingletonType , в яку крім стандартних параметрів, що передаються qmlRegisterType , необхідно також передати статичну функцію singletonProvider , яку також потрібно написати самим.


Структура проекту

Створіть Qt Quick проект, який містить такі файли:

  • SingletonQMLCpp.pro - профайл проекту
  • main.cpp - файл з main функцією
  • main.qml - основний файл qml
  • singletonclass.h - заголовний файл синглетону
  • singletonclass.cpp - файл вихідних кодів синглетону

Профайл проекту буде створено за замовчуванням і не змінюватиметься.

main.cpp

Почнемо з файлу main.cpp, де зареєструємо об'єкт майбутнього синглетону.

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml> // Подключаем для использования qmlRegisterSingletonType

#include "singletonclass.h" // Подключаем заголовочный файл SingletonClass

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

    // регистрируем объект синглетона через функцию singletonProvider, то есть передаём указатель на неё в качестве аргумента.
    qmlRegisterSingletonType<SingletonClass>("SingletonClass", 1, 0, "SingletonClass", singletonProvider);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

singletonclass.h

У заголовному файлі визначимо enum , який будемо використовувати для отримання певних повідомлень через "статичний" метод getMessage у шарі QML. У цьому файлі визначимо статичну функцію singletonProvider , яка створювати інстанс синглетона.

#ifndef SINGLETONCLASS_H
#define SINGLETONCLASS_H

#include <QObject>
#include <QQmlEngine>
#include <QJSEngine>

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

    enum class Message {
        Info,
        Debug,
        Warning,
        Error
    };
    // Регистрация enum для испоьлзования в QML
    Q_ENUM(Message)

    // Чтобы использовать этот метод в QML, объявите его на Q_INVOKABLE
    Q_INVOKABLE QString getMessage(Message message);

signals:

public slots:
};

static QObject *singletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)

    SingletonClass *singletonClass = new SingletonClass();
    return singletonClass;
}

#endif // SINGLETONCLASS_H

Зауважте, що getMessage не повинен бути статичним, щоб виступати як статичний метод Типу в QML.

singletonclass.cpp

У цьому файлі дана реалізація методу getMessage.

#include "singletonclass.h"

SingletonClass::SingletonClass(QObject *parent) : QObject(parent)
{

}

QString SingletonClass::getMessage(SingletonClass::Message message)
{
    switch (message)
    {
        case Message::Info:
            return "This is Info Message";
        case Message::Debug:
            return "This is Debug Message";
        case Message::Warning:
            return "This is Warning Message";
        case Message::Error:
            return "This is Error Message";
        default:
            return "Nothin not found";
    }
}

main.qml

А тепер скористаємося цим синглетоном типом в QML.

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

import SingletonClass 1.0 // Подключаем Синглетон


Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Singleton Class")

    ListView {
        anchors.fill: parent
        delegate: Item {
            height: 48
            width: parent.width
            Text {
                anchors.fill: parent
                text: model.text

                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }

        model: listModel
    }

    ListModel {
        id: listModel

        // Нет возможности использовать методы и функции сразу для property в ListElement, поэтому использован такой хак
        Component.onCompleted: {
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Info)})
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Debug)})
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Warning)})
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Error)})
        }
    }
}

Підсумок

В результаті буде отримано програму, яка виведе чотири повідомлення у своєму вікні.

Таким чином через синглетон об'єкт у QML додається можливість використання cpp методів як статичні.

Завантажити архів з проектом

Вам це подобається? Поділіться в соціальних мережах!

3
  • 02 жовтня 2018 р. 01:05

In the debugger, I could not manage to see if the constructor is called once for all or if is called at every occurence from QML. Do you know?

Evgenii Legotckoi
  • 05 жовтня 2018 р. 18:11

For QML constructor will be called once.

It works some differently from classic Singleton, but instance will be one.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up