What is the best practice for passing data from C++ to QML?
-
I have an existing Qt widgets application that I would like to start transitioning to QML. The application has some C++ data with a complex structure. It can't be forced into any of the Qt models that I am aware of (list, table, or tree). However, it does exist in
QObject
-derived classes, and I can add the appropriate macros to these classes to make them workable in QML (QML_ELEMENT
,Q_PROPERTY
,Q_INVOKABLE
, etc.).What would be the best practice for getting this data from C++ to QML? I will probably be replacing the application with QML one piece at a time, using multiple
QQuickWidget
s to embed the QML in the widgets app. So I'm curious about best practice in two scenarios:- An application that has bits and pieces of QML
- A pure QML application
Some options that I am aware of:
- Using singletons with
QML_SINGLETON
orqmlRegisterSingletonInstance(...)
- Setting context properties with
QQmlContext::setContextProperty(...)
- Setting initial/required properties with
QQmlApplicationEngine::setInitialProperties(...)
-
You can use
Q_PROPERTY in C++ classes to define properties for direct access from QML
or
Model-View Approach(for example table data)class LargeDataModel : public QAbstractTableModel { Q_OBJECT public: explicit LargeDataModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash<int, QByteArray> roleNames() const override; void loadData(const QVector<QVector<QVariant>> &newData); private: QVector<QVector<QVariant>> m_data; };
Look for models in Qt QML to fit your needs.
or use singleton QtObject qml files to define global geometry or stylesheet, etc. data for global access of all qml files.
-
https://doc.qt.io/qt-6/qtqml-cppintegration-overview.html
The flowchart is a good reference. -
@JoeCFD Thanks for linking that!
From what I can tell, that chart is mostly about registering types with QML (although it does touch on the singleton option). I'm curious about moving the actual data from C++ to QML. To be more specific, if my data is loaded up using some C++ code in a model layer, how do I get that data (which exists in C++ objects) into the QML context? What is the actual method I should call at that point, assuming all the necessary types are already registered? Or do I just add it all to a singleton, which is available from both C++ and QML?
I ask this in the context that the majority of my app is Qt widgets. It will only slowly be replaced with QML, piece by piece. So the driving code is going to remain C++ for a while. And I'll have a bunch of QML contexts floating around for the various
QQuickWidget
s. -
You can use
Q_PROPERTY in C++ classes to define properties for direct access from QML
or
Model-View Approach(for example table data)class LargeDataModel : public QAbstractTableModel { Q_OBJECT public: explicit LargeDataModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash<int, QByteArray> roleNames() const override; void loadData(const QVector<QVector<QVariant>> &newData); private: QVector<QVector<QVariant>> m_data; };
Look for models in Qt QML to fit your needs.
or use singleton QtObject qml files to define global geometry or stylesheet, etc. data for global access of all qml files.
-
@JoeCFD Thanks for your answer. From what I understand, that helps to explain what's required in a pure QML application.
I also had a second question, regarding an application that is hybrid QML and Qt widgets (using
QQuickWidget
). But I think that maybe this got lost in my original question, so I will ask a new question specifically about the hybrid scenario.Link to the new question: https://forum.qt.io/topic/161561/what-is-the-best-practice-for-passing-c-data-to-qml-contained-in-a-qquickwidget
-
-
@peter-thompson Better not to mix them. I mixed only one gstreamer qml sink in a widgets app. It is doable, but messy.
5/6