1

I have a grid with nested elements(text and mouse area within a rectangle):

    property variant colorArray: ["#00bde3", "#67c111", "#ea7025"]

...
Grid{
        rows: 5
        columns: 5
        spacing: 5
        anchors.centerIn: parent
        Repeater{
            id: gridRect
            model: 25
            Rectangle{
                id: rect
                width: 50
                height: width
                color: "white"
                radius: 5
                Text {
                    id: tttt
                    anchors.centerIn: parent
                    color: "lightBlue"
                    text : index
                }
                MouseArea{
                    anchors.fill: parent
                }

            }
        }

    }

and I want to change the color of some squares and texts within the grid randomly but I don't know how to access them, I tried using timers like this:

Timer {
        id: alfa
        interval: 500; running: true; repeat: true
        onTriggered: {

            /*if random square not white , a color from color array is picked to change it
            else random square.color = "white"*/
        }

    }
    Timer {
        id: beta
        interval: 1000; running: true; repeat: true
        onTriggered: {
           //changes the text of a random tttt element in the grid
        }
    } 

I tried many things but it all failed, like using property binding seemed to change the whole grid color & text not a single square, I can't understand how to access nested elements and repeaters children at all and the documentation isn't helping what should I do?

2 Answers2

1

Since they want to modify the information that the view shows, you should not interact with it directly but create a model and through it you should modify the data:

property variant colorArray: ["#00bde3", "#67c111", "#ea7025"]

ListModel{
    id: mymodel
    Component.onCompleted: {
        for(var i=0; i<25; i++){
            mymodel.append({"text": ""+i, "color": "white"})
        }
    }
}
Grid{
    rows: 5
    columns: 5
    spacing: 5
    anchors.centerIn: parent
    Repeater{
        id: gridRect
        model: mymodel
        Rectangle{
            id: rect
            width: 50
            height: width
            color: model.color
            radius: 5
            Text {
                id: tttt
                anchors.centerIn: parent
                color: "lightBlue"
                text : model.text
            }
            MouseArea{
                 anchors.fill: parent
            }
        }
    }
}
Timer{
    id: alfa
    interval: 500; running: true; repeat: true
    onTriggered: {
        var random_color = colorArray[Math.floor(Math.random() * colorArray.length)]
        var random_ix = Math.floor(Math.random() * mymodel.count);
        var elem = mymodel.get(random_ix)
        elem.color = elem.color === "white" ? random_color : "white"
    }
}
Timer{
    id: beta
    interval: 1000; running: true; repeat: true
    onTriggered: {
        // https://stackoverflow.com/a/38620178
        var random_str = "";
        var alphabet = "abcdefghijklmnopqrstuvwxyz";
        while (random_str.length < 6) {
            random_str += alphabet[Math.floor(Math.random() * alphabet.length)];
        }
        var random_ix = Math.floor(Math.random() * mymodel.count);
        var elem = mymodel.get(random_ix)
        elem.text = random_str
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
0

You can think of repeaters working as if you had just copied that Rectangle into the Grid 25 times. This means in order to access one of them, you would have to access children of the Grid.

You could either use eyllanesc's response from earlier, and edit the data in ListModel (this is, I think, the correct way of doing this)

Or, you can use The 'children' function that should be present in Grid as well, which returns an array of children that the Grid owns, which would be the Rectangles you've added via Repeater.

I would personally do this the ListModel way.

Pepe
  • 1