QMap exposed as QProperty gives qml undefined
-
I am attempting to develop a singleton C++ class and make it accessible to QML using the
qmlRegisterSingletonType()
method. This class is designed to manage aQMap<QString, QString>
property containing pairs of colors. I intend to utilize these colors in my QML elements for theme-related purposes.AppTheme.hpp
#ifndef APPTHEME_H #define APPTHEME_H #include <QObject> #include <QMap> #include <QQmlEngine> #include <QFile> #include <QJsonDocument> #include <QJsonObject> #include <QJsonArray> class AppTheme : public QObject { Q_OBJECT Q_DISABLE_COPY(AppTheme) public: explicit AppTheme(QObject *parent = nullptr); ~AppTheme(); // Fields; private: static AppTheme* m_Instance; QMap<QString, QString> m_Colors; Q_PROPERTY(QMap<QString, QString> Colors READ Colors WRITE setColors NOTIFY ColorsChanged FINAL) // Methods; public: static AppTheme* instance(QQmlEngine *engine, QJSEngine *scriptEngine); void loadFromJsonFile(const QString &filePath); QMap<QString, QString> Colors() const; void setColors(const QMap<QString, QString> &newColors); // Signals; signals: void ColorsChanged(); // Slots; public slots: void extractColors(const QString &filePath); }; #endif // APPTHEME_H
AppTheme.cpp
#include "AppTheme.h" AppTheme* AppTheme::m_Instance = nullptr; AppTheme::AppTheme(QObject *parent) : QObject{parent} , m_Colors() {} AppTheme::~AppTheme() {} QMap<QString, QString> AppTheme::Colors() const { return m_Colors; } void AppTheme::setColors(const QMap<QString, QString> &newColors) { if (m_Colors == newColors) return; m_Colors = newColors; emit ColorsChanged(); } void AppTheme::extractColors(const QString &filePath) { loadFromJsonFile(filePath); } AppTheme *AppTheme::instance(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine); Q_UNUSED(scriptEngine); if (!m_Instance) { m_Instance = new AppTheme(); } return(m_Instance); } void AppTheme::loadFromJsonFile(const QString &filePath) { QMap<QString, QString> map; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Could not open JSON file:" << filePath; return; } QByteArray jsonData = file.readAll(); file.close(); QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); QJsonObject rootObject = jsonDoc.object(); // Assuming your JSON structure is an object with key-value pairs for (auto it = rootObject.begin(); it != rootObject.end(); ++it) { // Assuming keys and values are both strings map[it.key()] = it.value().toString(); } // Using QProperty binding. setColors(map); qDebug() << map; qDebug() << m_Colors; }
main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "AppTheme.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; qmlRegisterSingletonType<AppTheme>("AppTheme", 1, 0, "AppTheme", &AppTheme::instance); const QUrl url(u"qrc:/QTodo/main.qml"_qs); QObject::connect( &engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml
import QtQuick import QtQuick.Controls ApplicationWindow { id: root width: 640 height: 800 visible: true title: qsTr("QTodo") Component.onCompleted: { AppTheme.extractColors("C:/Users/Saviz/Desktop/QML projects/QTodo/QTodo/colors.json"); // This gives qml undefined error. console.log(AppTheme.Colors["CustomColor"]) } }
It effectively reads the file and generates the correct QMap. However, when attempting to use it in QML to set the color property of my rectangle, I encounter undefined behavior in QML. The debugging output is as follows:
QMap(("CustomColor", "#ff0000"))
QMap(("CustomColor", "#ff0000"))
qml: undefinedThe QMap is correctly generated, but in QML, it appears unable to recognize the string as a color.
JSON file
{ "CustomColor": "#ff0000" }
Any reason why this is happening?
-
@Saviz
I think is not possible to expose a QMap directly to QML,
https://doc.qt.io/qt-6/qtqml-cppintegration-data.html#sequence-type-to-javascript-arrayMaybe one should use a QVariantMap
https://doc.qt.io/qt-6/qtqml-cppintegration-data.html#qvariantlist-and-qvariantmap-to-javascript-array-and-object -