1
votes

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();
                        }
                    }
                }
            }
        }
    }
}
1
Your question is unclear, in large part of your question you complain about "your possible solution" which is clearly not the right one, what is your specific objective? You point out How can I set a property on every button? Which is abstract so my question is: what property do you want to modify specifically?eyllanesc
I want to set a property on every item of the grid. I called them Button. I don't have a "possible solution" - I have experiments in a for loop, iterating over either the grid or the model - and in every try, when I put a property name after the item, I get undefined. @eyllanescThalia
Attempts are "possible solutions." My criticism is that in much of your post you focused on your attempts without first pointing out what your specific objective was, for example something more clear would be: I want to modify the property X of the element Y shown in the following code, to make I have tried P, Q and R but I get these problems. Well, bypassing that I have published an illustrative example.eyllanesc
@eyllanesc Thank you, in my defense, what I wanted to do is modify any property of all items, so that in the items I can use a function onPropertyChanged - because it was the only way I found to signal all items.Thalia

1 Answers

1
votes

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});
        }
    }
}