Setting the model for a QQuickWidget
-
To set the model for a QQuickView you use
setInitialProperties
, e.g._contents = new QQuickView; _contents->setInitialProperties({{QLatin1String("model"), QVariant::fromValue(&_model)}}); _contents->setSource(QUrl(QStringLiteral("qrc:/Launcher.qml")));
This works fine with my model. If I switch to using a QQuickWidget, however, there is no
setInitialProperties
method, and I can't figure out what the equivalent is. For example,_contents = new QQuickWidget (this); _contents->setProperty("model", QVariant::fromValue(&_model)); _contents->setSource(QUrl(QStringLiteral("qrc:/Launcher.qml")));
(where _model here is the same QAbstractListModel-derived-class that worked with the QQuickView). What am I missing here to get the C++ model to talk to my QML in a QQuickWidget?
-
@Chris-Hennes To make a property visible globally in QML, you need to add it to root context object of the QML engine. So:
_contents = new QQuickWidget (this); _contents->setSource(QUrl(QStringLiteral("qrc:/Launcher.qml"))); _contents->rootContext()->setContextProperty("model", QVariant::fromValue(&_model));
-
@sierdzio Thank you for that information. So now I am trying:
_contents = new QQuickWidget (this); _contents->rootContext()->setContextProperty(QLatin1String("model"), QVariant::fromValue(&_model)); _contents->setSource(QUrl(QStringLiteral("qrc:/Launcher.qml"))); setCentralWidget(_contents); _contents->show();
The QML is trivial:
import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQml 2.12 ListView { width: 200 height: 250 delegate: Text { required property string baseName required property string creationTime text: "Recent file: " + baseName + ", " + creationTime } }
but all I get is a blank screen. The same QML works fine with QQuickView, and the QQuickWidget works fine if I, e.g. draw a rectangle, etc. So it seems to me the problem is those few lines of C++ -- I'm clearly missing some critical step to connect the model to the widget.
-
@Chris-Hennes You are not setting the model anywhere in your ListView so it will display an empty list.
ListView { model: model
Also, having
model
as the name of your model might clash withmodel
property of ListView, maybe better rename it. -
Using context properties should be avoided ( https://doc.qt.io/qt-6/qtqml-cppintegration-contextproperties.html ) and exposing your C++ objects as QML singletons should be preferred :
https://doc.qt.io/qt-6/qtqml-cppintegration-overview.html#choosing-the-correct-integration-method-between-c-and-qml -
@sierdzio I'm trying to follow the example here: https://doc.qt.io/qt-6/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel-subclass
(and again, this works correctly, with no modifications to the QML, if I put it in a QQuickView instead of a QQuickWidget).
@GrecKo thanks for the links. I'm not sure how to follow the flowchart there, though, I am new to QML so the terminology doesn't mean anything to me (which is why I was trying to stay close to the example I link to above). I guess for a C++ model interacting with a QML view, I want the C++ side to be a QML_ELEMENT?
-
@GrecKo said in Setting the model for a QQuickWidget:
Using context properties should be avoided
Ah, it shows that I'm still stuck on Qt 5 on my current project :D Thanks for the links and info!
-
Ah, it shows that I'm still stuck on Qt 5 on my current project :D Thanks for the links and info!
I am too (we support compilation with both Qt5 and Qt6) -- my real problem is that we currently support compilation on Ubuntu 20.04LTS, which is still Qt 5.12, so large amounts of the current best-practices advice and documentation aren't relevant. I have been unable to come up with a working solution when using the non-context-properties methods because I can't get the cMake project to compile using the older setup commands. I think I'm stuck using the context properties, which of course I still can't get to work with QQuickWidget.
-
@Chris-Hennes going back to what sierdzio suggested you try, in this line:
_contents->rootContext()->setContextProperty(QLatin1String("model"), QVariant::fromValue(&_model));
try naming the property something other than
"model"
(let's say"myModel"
) and, in your QML, add to your list view:ListView { model: myModel ...
-
I ran into this issue myself when using QQuickWidget (since you're certainly going to want to be communicating between C++ and Qt Quick in that case). The original comment about
setInitialProperties
really triggered me, since that means there wasn't parity between QQuickWidget and QQuickView in a way that doesn't make sense. The same was true of the more modernloadFromModule
pattern. So I created a couple patches to at least to try and rectify this in 6.9:
https://codereview.qt-project.org/c/qt/qtdeclarative/+/586483/2
https://codereview.qt-project.org/c/qt/qtdeclarative/+/586520/1
But also I my case, that doesn't help me "today". I agree that using a QML Singleton is the correct solution over setting a context property, but that still led me to the issue that I wanted to do that the Modern/Correct way, but I didn't really understand from the docs how to get access to that Singleton from the C++ side. I found that this was the correct documentation page that explained that:
https://doc.qt.io/qt-6/qtqml-cppintegration-exposecppstate.html
But basically this is what the C++ code would look like:Singleton *singleton = engine->singletonInstance<Singleton *>("MyModule", "Singleton"); singleton->setThing(77);