how to change the model of a view
-
Hi all -
I have a QML view which is going to use one of two models. Which model isn't determined until relatively late in program startup. Here's the QML:
ListModel { id: bottleModel_16 ... } ListModel { id: bottleModel_19 ... } Column { Repeater { model: (reagentManager.bottleList().length === 16) ? bottleModel_16 : bottleModel_19 ...
This doesn't work because the QML "executes" before the bottleList is populated, so the length returns as 0.
So...what's a preferred method of updating the model? Not the model itself, but which one to use in the view? (Hopefully that's clear.)
Thanks...
-
Use a property that changes when the list length does as part of the binding. It would be convenient if that property happened to be the length or at involved in fetching it, but it doesn't have to be. Perhaps reagentManager is that property.
model: (reagentManger.bottleList().length + reagentManager.zeroValueProperty === 16) ? bottleModel_16 : bottleModel_19
Or emit a signal and reassign the model in a connected slot.
-
@mzimmers
this looks like bottleList is an Invokable function rather than a property, which is the problemmodel: (reagentManager.bottleList().length === 16) ? bottleModel_16 : bottleModel_19
its is check only once, onCreation.
Make the length of the model a proper Q_PROPERTY and it should work just fine:model: (reagentManager.bottleListLength === 16) ? bottleModel_16 : bottleModel_19
or make the bottleList a correct Q_PROPERTY and this should work as well:
model: (reagentManager.bottleList.length === 16) ? bottleModel_16 : bottleModel_19
-
@J-Hilk I would like very much to make my bottle list object a Q_PROPERTY. In fact, that was my first attempt, but I ran into problems. Here's my source code:
struct Bottle : public QObject { ... typedef QList<Bottle *> Bottles; class ReagentManager : public QObject { Q_OBJECT private: Bottles m_bottleList; public: Q_PROPERTY(Bottles bottleList READ getBottleList MEMBER m_bottleList) ...
And my QML:
Column { id: bottles Repeater { model: (reagentManager.bottleList.length === 19) ? bottleModel_19 : bottleModel_16
I get a runtime error:
TypeError: Cannot read property 'length' of undefined
On the line that attempts to use the length property.
-
@mzimmers said in how to change the model of a view:
Q_PROPERTY(Bottles bottleList
Make your QML facing list a list of QObject*. Or register Bottles and Bottle with the meta object system.
Q_PROPERTY(QList<QObject*> bottleList
This means your getBottleList will have to build up a QList<QObject> list each time.
-
@fcarney yeah, I realized that I'd made a couple of mistakes in my header file.
typedef QList<Bottle *> Bottles; Q_DECLARE_METATYPE(Bottles) ... Q_PROPERTY(Bottles bottleList MEMBER m_bottleList NOTIFY bottleListChanged) signals: void bottleListChanged();
The signal is emitted at the end of an updater routine that's called from QML when the view becomes visible:
onVisibleChanged: { if (visible) { reagentManager.updateBottleList()
I got an error when I tried to declare Bottle as a metatype (possibly because it's a struct, not a class), but the program seems to work without that.
So, declaring the metatype greatly simplified the code, and the signal handles the update. Thanks for the help!