Поняття статичних методів, які використовуються в 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 методів як статичні.
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?
For QML constructor will be called once.
It works some differently from classic Singleton, but instance will be one.