Thalia
Thalia

Reputation: 14615

Qml: How to set a property to all GridView items

I am trying to make a change to all items of a GridView.
I have tried to iterate through either the model or the grid, I looked at similar examples on the web, but everything I try ends with Cannot read property 'buttonText' of undefined.

It seems to me that the problem is that the interpreter can't figure out that the item from the grid or model is a Button. But I don't know how to cast it.

If I change the log to only display the item, not any property, (see code snippet), it seems that it knows it is an item... see my experiments below.

The only thing I can make work is set a property (or call a signal, or a function) from the delegate. But that only affects one grid item, not all.

How can I set a property on every item of the grid ? Alternatively, how can I send a signal, or call a function, on every item?

My experiments are in function changeEverythingFunction()

file: Button.qml

Item
{
    id: itemButton
    signal changeEverything

    property int buttonIndex
    property string buttonText

    ...
}

file: Model.qml

Item
{
    id: modelItem

    ListModel
    {
        id: listModel
    }

    property int buttonCount: listModel.count

    function changeEverythingFunction()
    {
    //    for (var i = 0; i < buttonCount; i++)
    //        listModel.setProperty(i, buttonText, "abc")

        for(var childIndex in gridItems.contentItem.children) 
        {
            console.log(listModel.get(childIndex).buttonText)   // Cannot read property 'buttonText' of undefined
            console.log(gridItems.contentItem.children[childIndex].buttonText) // Cannot read property 'buttonText' of undefined
            console.log(gridItems.contentItem.children[childIndex]["buttonText"])   // undefined (I saw this in a SO example)

            var item = gridItems.contentItem.children[childIndex]
            console.log(item)   // qml: QQuickItem(0xe496370)
        }
    }

    MouseArea
    {
        ....
        Rectangle
        {
            ...

            GridView
            {
                id: gridItems

                anchors.fill: parent
                clip: true
                model: listModel

                delegate: Item
                {
                    id: buttonDelegate

                    Button
                    {
                        buttonIndex: gridId
                        buttonText: itemText

                        onChangeEverything:
                        {
                            changeEverythingFunction();
                        }
                    }
                }
            }
        }
    }
}

Upvotes: 1

Views: 1552

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

Your approach is in the opposite direction: Your approach is to obtain the item of the view and modify it, but the approach that Qt points out is that the view reflects the information of the model and modifies it when necessary.

The following is a simple example where every time you press on the button with "change me" text increasing the number it shows, but if you press the button with "change all" text it will change all the numbers. As it is observed everything is done through the model, not through the view that are only used to display information or receive user interaction.

import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14

Window {
    visible: true
    width: 640
    height: 480
    ListModel{
        id: listmodel
    }
    function changeAll(){
        for(var i=0; i< listmodel.count; ++i){
            listmodel.setProperty(i, "number", listmodel.get(i).number + 1)
        }
    }
    GridView{
        id: grid
        anchors.fill: parent
        clip: true
        model: listmodel
        cellHeight: 120
        cellWidth: 120
        delegate: Item {
            width: grid.cellWidth; height: grid.cellHeight
            Column {
                anchors.fill: parent
                Text { text: model.number; anchors.horizontalCenter: parent.horizontalCenter }
                Button{text: "change me"; onClicked: model.number +=1}
                Button{text: "change all"; onClicked: changeAll()}
            }
        }
    }
    Component.onCompleted: {
        for(var i=0; i < 10; ++i){
            listmodel.append({"number": 0});
        }
    }
}

Upvotes: 1

Related Questions