First of all, I'm new to Qt6 and QML, so maybe I am missing something obvious.
I'm trying to link a C++ model to a ListView in QML from a QObject
property.
From this doc I should be able to use a List<QObject*>
as a static model in a QML view.
However, in that example, the QList<QObject*>
is passed directly to a QQuickView
.
I would like to access the object list from a property of a QObject
I can already access in QML.
But when I try to do that, nothing is shown in the list view, and I don't know what I am doing wrong...
Also, QML reports me a warning (see below my example code).
Here a working minimal example of what I am trying to achieve:
backend.h
#ifndef BACKEND_H#define BACKEND_H#include <QObject>// Contains the data I want to display for each elementclass Item : public QObject{ Q_OBJECT Q_PROPERTY(QString name MEMBER m_name NOTIFY onNameChanged)public: Item(QString name, QObject *parent = nullptr) : QObject{parent}, m_name(name) {}signals: void onNameChanged();private: QString m_name {"NULL"};};// This class contains the model I want to display.// The data will be loaded before loading the QML file.// It can be switched between a mockup and a real backend depending on the context.class Backend : public QObject{ Q_OBJECT Q_PROPERTY(QString header MEMBER m_header NOTIFY onHeaderChanged) Q_PROPERTY(QList<QObject*> model MEMBER m_model NOTIFY onModelChanged)public: explicit Backend(QObject *parent = nullptr) : QObject{parent} { m_header = "Cpp Backend"; m_model.append(new Item {"Cpp"}); m_model.append(new Item {"backend"}); m_model.append(new Item {"is"}); m_model.append(new Item {"great!"}); } virtual ~Backend() override { for (QObject* item : m_model) delete item; }signals: void onHeaderChanged(); void onModelChanged();private: QString m_header; QList<QObject*> m_model;};#endif // BACKEND_H
main.cpp
#include <QGuiApplication>#include <QQmlApplicationEngine>#include <QQMLContext>#include "backend.h"int main(int argc, char *argv[]){ QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // Exposing the backend to QML with the name "cppBackend" Backend backend; engine.rootContext()->setContextProperty("cppBackend", &backend); const QUrl url(u"qrc:/TestBackend/Main.qml"_qs); QObject::connect(&engine,&QQmlApplicationEngine::objectCreationFailed,&app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec();}
Main.qml
import QtQuickWindow { width: 640 height: 480 visible: true title: qsTr("Hello World") ListModel { id: mockupList ListElement { name: "Hello" } ListElement { name: "World!" } ListElement { name: "How" } ListElement { name: "are" } ListElement { name: "you?" } } ListView { id: listView anchors.fill: parent anchors.margins: 20 spacing: 10 orientation: ListView.Vertical //model: mockupList // this works as expected model: cppBackend.model // this doesn't show anything in the listview delegate: Item { id: myItem required property string name width: label.width height: label.height Text { id: label text: myItem.name font.pointSize: 24 } } header: Text { width: parent.width horizontalAlignment: Text.AlignHCenter font.pointSize: 48 font.bold: true text: cppBackend.header // This works as expected } }}
When I use te mockupList
instead of the C++ backend, the items are displayed as expected.
However, when using the cppBackend
I'm getting this warning:
qrc:/TestBackend/Main.qml:30:13: Required property name was not initialized qrc:/TestBackend/Main.qml: 30
It seems that the property cppBackend.model
is accessed, but the items inside do not provide access to their properties as it seems it should to be done in the Qt doc...