Solved Update List Model created via QVariant::fromValue(QList<QObject*>))
-
Hi,
I have a
QList<QObject*> _mylist;
which I display in a
TableView
. To get the model for theTableView
I did_engine->rootContext()->setContextProperty("myList", QVariant::fromValue(_myList));
This is working fine, in principle. However, when I add new elements via
_myList.push_back(new MyItem(...));
I need to update the model. How is this done correctly? Right now I simply called
_engine->rootContext()->setContextProperty("myList", QVariant::fromValue(_myList));
again. However, with this approach, I also get error messages of this type:
qrc:/Screen.qml:158: TypeError: Cannot read property 'firstProperty' of null
Still, the new content gets displayed.
Thanks for your help! -
@maxwell31
According to the Qt doc:
http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html
your approach of re-usingsetContextProperty()
to update the view is correct:Note: There is no way for the view to know that the contents of a QList has changed. If the QList changes, it is necessary to reset the model by calling QQmlContext::setContextProperty() again.
To avoid the
typeError
warning you can check whetherobject
is null before you try to use itsfirstProperty
property, e.g.:someBinding: object ? object.firstProperty : someDefaultValue
Or you should defer using the object until you are sure the object has been created, e.g. using
Component.onCompleted
etc...To be honest, I also still struggle with QML's object creation order issues like this, especially when the layout has multiple model-based views which depend on each other.
-
Thanks for your post. The errors come from the TableViewColumns. If I modify them according to your suggestion
TableViewColumn { width: 80 title: "property" delegate: Text{ text: model ? model.firstProperty.toFixed(2):"" } }
The errors disappear. I guess using onComponentCompleted is not possible here, as the model already was present before calling setContextProperty again? So there is no other solution for this than checking for null?
-
@maxwell31
well, instead of setting the List directly as a context property, you could wrap it in a Qobject based class and make the List available via Q_Property macroQ_PROPERTY(QVariant myModel READ myModel NOTIFY myModelChanged)
Now, when you
emit myModelChanged()
, the QML part will update itself -
Good idea
-
@J-Hilk I think this would represent a problem anyways, because if you use the list in a repeater, QML is still not able to know when it changes so the first approach would need to be implemented again. Even if I call "emit myModelChanged", it doesn't work. It seems that the dataModel only updates with the emit when the size changes... so I remove the last element, emit de change, add it back, and emit again.