The notion of static methods that are used in QML differs somewhat from the classical one in C ++, when static methods are created in the class that can be used referring to the class name, rather than to a specific object. In the case of QML, things are somewhat different. In order to use such methods in QML, which are present in the C ++ class, it is necessary to register a Singleton object that will provide the required methods, and these methods should no longer be static in themselves. They should at least be labeled with the Q_INVOKABLE macro so that they can be used in QML.
To register Singleton , you need to use the qmlRegisterSingletonType function, which in addition to the standard parameters that are passed to qmlRegisterType, you must also pass the static singletonProvider function, which you also write yourself.
Project structure
Create a Qt Quick project that will contain the following files:
- SingletonQMLCpp.pro - Project profile
- main.cpp - File with main function
- main.qml - Main qml file
- singletonclass.h - Singleton header file
- singletonclass.cpp - Singleton source file
The project profile will be created by default and will not be changed.
main.cpp
Let's start with the file main.cpp, in which we will register the object of the future singleton.
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QtQml> // We connect to use qmlRegisterSingletonType #include "singletonclass.h" // We connect the header file SingletonClass int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // Register the singleton object through the function singletonProvider, that is, we pass the pointer to it as an argument. 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
In the header file, define enum, which we will use to get certain messages through the "static" getMessage method in the QML layer. In the same file, we define the static function singletonProvider , which will create a singleton instance.
#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 registration for use in QML Q_ENUM(Message) // To use this method in QML, declare it in 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
Note that getMessage does not have to be static to act as a static Type method in QML.
singletonclass.cpp
This file provides the implementation of the getMessage method.
#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
And now let's use this singleton type in QML.
import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 import SingletonClass 1.0 // Connect Singleton 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 // There is no way to use methods and functions directly for property in ListElement, so this hack is used 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)}) } } }
Conclusion
As a result, an application will be received that will display four messages in its window.
Thus, through the singleton object in QML, the ability to use cpp methods as static is added.
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.