How can you know when all the delegates of a View or Repeater have been created once the model is set?



  • Hi
    I am having synchronization problems within my C++/QML application.

    After I set the model property of a Repeater inside a Column which functions as a drawer of sorts. Then, I reparent some of the items in that Column to a Grid.

    In my first version, the model was a QML XmlListModel, and then the above worked fine.
    Now, I have replaced the XmlListModel by an equivalent C++ model, exposed as a custom QML type, but things now no longer work, because the reparenting is now apparently started before the Repeater items are created.

    In this new approach, I therefore need to wait until all Repeater items have been created. Is there an event I can use for this, other than to count (in the delegate's onCompleted()) the number of instantiated items myself? (I am already using that convoluted approach for another model/view part, but I'm wondering if there is a better way).



  • Hi,

    maybe the problem is in c++, how are you linking c++ to qml you Register the Type in c++?



  • Hi @Diackne
    Thanks for reacting.

    you Register the Type in c++

    Yes, I register the model as a QML-type in C++, having implemented, amongst others, the following methods:

        int rowCount(const QModelIndex & parent = QModelIndex()) const;
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
        bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    
        Q_INVOKABLE QVariantMap get(int row);
    


  • @Diracsbracket said in How can you know when all the delegates of a View or Repeater have been created once the model is set?:

    Q_INVOKABLE QVariantMap get(int row);

    Q_INVOKABLE is the problem, you maybe in your qml code call this get(N) but not the reactive way!! if c++ ends after the first call of get(N) your result of get(N) return empty
    maybe you need follow this idea

        ctxt->setContextProperty("myModel", &model);
    
    Repeater {
        model: myModel  // this notify c++ --> Qml
        delegate: Text { text:  type + ", " + size }
    }
    

    Model Views Data

    but in qml who you pass the model only get(N) or inside repeater and the repeater have the model?



  • @Diackne

    At the time I created this post, I did it as follows:

    Flickable{
                id: sourceFlick
                ....
                 Column {
                    id: buttonList
    
                    Repeater {
                        model: xmlButtonModel
                        ...
                        delegate: DragTile {}
                    }
           }
    }
    

    I used a Repeater because I needed all the delegates to be instanciated at all times (as opposed to only when they are visible). But in the meanwhile, I learned that I could do the same with a ListView by setting the cacheBuffer to an appropriate value, and now I do things like this:

    ListView {
                id: buttonList
                ...
                model: xmlButtonModel
                ....
                delegate: DragTile {}
    }
    

    The model and ListView are part of an Item, of which several instances are created dynamically, based on the number of XML files found in a directory:

    Item {
        id: layout
    
        XmlListModel {
            id: xmlButtonModel
            ...
            onStatusChanged: {
                if (status == XmlListModel.Ready) {
                    ...
                    Js.createGridPages()
                     ...
                }
            }
        }
    
        Rectangle {
            id: drawer
            ...
            ListView {
                id: buttonList
                ...
                model: xmlButtonModel
                ....
                delegate: DragTile {}
           }
        }
    
        Item {
            id: layoutItem
            ...
            SwipeView {
                id: swipeView
                ...
                contentItem: ListView {
                    ...
                    model: ListModel {
                        id: viewModel
                    }
    
                    delegate: ButtonGrid {}
                }
            }
        }
    }
    

    So for a given layout Item, once the XML model is loaded, the layout is populated by Js.createGridPages(), which creates the pages in swipeView, each page containing a Grid of cells to which items of buttonList are reparented based on a user-preferences file...

    I must note that this reparenting process even fails occasionally when simply rebuilding + autolaunching the app via Qt Creator (target device is Android), even when I don't use my faster C++ XML model. The error is always the same: some of the DragTile delegates of my buttonList is still undefined.



  • I finally found what was happening.

    I incorrectly assumed (from a few debug output samples) that when using a Repeater to instantiate the cells of my Grid, the cells would always be listed first in the children list of Grid and that the Repeater item would always be listed as the last child (i.e. cells would be "inserted" in the list before the Repeater as they got instantiated) .

    Based on that assumption, I directly used the cell index (let's say i) to get the corresponding item as children[i].

    The above assumption was apparently wrong: once in a while, the Repeater item would not always be the last child, and a cell could come after it... Therefore, my above approach of using the grid cell index to retrieve the item sometimes resulted in getting the Repeater item instead...

    To avoid this, I have eliminated the Repeater, and simply instantiate the cells dynamically in the Component.onCompleted() handler. This allows me to directly use the grid cell index to retrieve the item from the children list, not having to worry about other types of children...



  • Why not use the Repeater's itemAt(index) method?



  • @GrecKo
    That's a good one, I didn't think there would be such a method! Thanks for pointing it out!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.