Das Konzept statischer Methoden, die in QML verwendet werden, unterscheidet sich etwas von dem klassischen in C++, wenn statische Methoden in einer Klasse erstellt werden, die verwendet werden können, indem auf den Klassennamen und nicht auf ein bestimmtes Objekt verwiesen wird. Bei QML liegen die Dinge etwas anders. Um solche Methoden in QML zu verwenden, die in einer C++-Klasse vorhanden sind, muss ein Singleton-Objekt registriert werden, das die erforderlichen Methoden bereitstellt, und diese Methoden müssen nicht mehr selbst statisch sein. Sie müssen mindestens mit dem Makro Q_INVOKABLE gekennzeichnet sein, um in QML verwendet werden zu können.
Um ein Singleton zu registrieren, müssen Sie die Funktion qmlRegisterSingletonType verwenden, in der Sie zusätzlich zu den Standardparametern, die an qmlRegisterType übergeben werden, auch die statische Funktion singletonProvider übergeben müssen, die du musst auch selbst schreiben.
Projektstruktur
Erstellen Sie ein Qt Quick-Projekt, das die folgenden Dateien enthält:
- SingletonQMLCpp.pro - Projektprofil
- main.cpp - Datei mit Hauptfunktion
- main.qml - Haupt-qml-Datei
- singletonclass.h - Singleton-Header-Datei
- singletonclass.cpp - Singleton-Quellcodedatei
Das Projektprofil wird standardmäßig erstellt und nicht geändert.
main.cpp
Beginnen wir mit der Datei main.cpp, in der wir das Objekt des zukünftigen Singletons registrieren werden.
#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
In der Header-Datei definieren wir enum , die wir verwenden, um bestimmte Nachrichten über die "statische" Methode getMessage in der QML-Schicht abzurufen. In derselben Datei definieren wir die statische Funktion singletonProvider , die eine Singleton-Instanz erstellt.
#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
Beachten Sie, dass getMessage nicht statisch sein muss, um als statische Methode für einen Typ in QML zu fungieren.
singletonclass.cpp
Diese Datei enthält die Implementierung der Methode 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
Lassen Sie uns nun diesen Singleton-Typ in QML verwenden.
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)}) } } }
Insgesamt
Das Ergebnis ist eine Anwendung, die vier Meldungen in ihrem Fenster anzeigt.
Daher wird durch das Singleton-Objekt in QML die Möglichkeit hinzugefügt, cpp-Methoden als statische Methoden zu verwenden.
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.