Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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...



  • hi @mzimmers
    i would assign the model after bottle List is populated



  • @LeLev the architecture of this application is such that all the QML views are loaded up front, not on an "as needed" basis. Is it possible to re-assign the model?

    Thanks...



  • @mzimmers said in how to change the model of a view:

    Is it possible to re-assign the model?

    why not try it ? :) I think it is possible



  • 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.


  • Moderators

    @mzimmers
    this looks like bottleList is an Invokable function rather than a property, which is the problem

    model: (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!


Log in to reply