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

Problem with access to ListElement's proporty after delegate's function calling



  • Hello everybody!

    A have a little problem with ListModels.

    Below I have attached a simple example of my problem. There I create 3 ListElements of my delegate object. My delegate object has onClecked handler, that changes text property. Also I wont to chenge ListElements's text property from my main.qml file. I do it in separate Button object, in his onClicked handler.

    When I just change text property by Button's handler all ok, when I just change text property by delegates's handler all ok too. But when I try to chenge text by Button's handler after changing by delegate's handler, Button's handler has no effect.

    main.qml

    Window {
        title: qsTr("Hello World")
        visible: true
        width: 300
        height: 300
        Item {
            width: 300
            height: 30
            ListModel {
                id: myModel
                ListElement { name: "ONE" }
                ListElement { name: "TWO" }
                ListElement { name: "THREE" }
            }
            Component {
                id: myDelegate
                MyDelegate {
                    name: model.name
                }
            }
    
            ListView {
                id: myList
                delegate: myDelegate
                model: myModel
                anchors.fill: parent
                orientation: Qt.Horizontal
                layoutDirection: Qt.RightToLeft
            }
        }
        Button {
            x: 100
            y: 100
            width: 100
            height: 30
            text: "thisOnClicked"
            onClicked: {
                for(var j=0; j<myModel.count; j++) {
                     myModel.get(j).name = "byBottomButton"
                }
            }
        }
    
    }
    

    MyDelegate.qml

    Button {
        id: itemDelegate
        property string name: "NONE"
        property bool check: false
        text: name
        onClicked: {
            if(check) {
                check = false
                text = "unchecked"
            } else {
                check = true
                text = "checked"
            }
        }
    }
    

    I try to understand, that happens here, but I can't... Thank you for reading this.



  • This is because your text property of MyDelegate is binded to name property, but not backwards (since there is no two-way bindings in QML), so setting text manually will not change name property. I've wrote a working example down:

        import QtQuick 2.12
        import QtQuick.Controls 2.12
        import QtQuick.Window 2.12
        
        Window {
            visible: true
            width: 640
            height: 480
            title: qsTr("Hello World")
        
            ListView {
                id: view
                anchors.fill: parent
                spacing: 10.0
        
                model: ListModel {
                    ListElement { name: "One" }
                    ListElement { name: "Two" }
                    ListElement { name: "Three" }
                }
        
                delegate: ItemDelegate {
                    width: ListView.view.width
                    text: model.name
                    checkable: true
                    onClicked: {
                        view.model.setProperty(model.index, "name", checked ? "Checked" : "Unchecked")
                    }
                    background: Rectangle {
                        color: "lightsteelblue"
                    }
                }
            }
        }
    


  • Probably some bindings brokes when you are writing values directly into properties. The right way to set any data in your case is to use setProperty method of ListModel.



  • Thanks for answer, IntruderExcluder.

    I replaced myModel.get(j).name = "byBottomButton" to
    myModel.setProperty(j, "name", "byBottomButton"), but it still don't work right..



  • This is because your text property of MyDelegate is binded to name property, but not backwards (since there is no two-way bindings in QML), so setting text manually will not change name property. I've wrote a working example down:

        import QtQuick 2.12
        import QtQuick.Controls 2.12
        import QtQuick.Window 2.12
        
        Window {
            visible: true
            width: 640
            height: 480
            title: qsTr("Hello World")
        
            ListView {
                id: view
                anchors.fill: parent
                spacing: 10.0
        
                model: ListModel {
                    ListElement { name: "One" }
                    ListElement { name: "Two" }
                    ListElement { name: "Three" }
                }
        
                delegate: ItemDelegate {
                    width: ListView.view.width
                    text: model.name
                    checkable: true
                    onClicked: {
                        view.model.setProperty(model.index, "name", checked ? "Checked" : "Unchecked")
                    }
                    background: Rectangle {
                        color: "lightsteelblue"
                    }
                }
            }
        }
    

  • Qt Champions 2018

    @IntruderExcluder said in Problem with access to ListElement's proporty after delegate's function calling:

    onClicked: {
        view.model.setProperty(model.index, "name", checked ? "Checked" : "Unchecked")
    }
    

    Note that this is equivalent to:

    onClicked: model.name = checked ? "Checked" : "Unchecked"
    

    The latter has the advantage to work with all models and not only ListModel, it calls QAbstractItemModel::setData.



  • It really works!

    Thank you, IntruderExcluder, GrecKo.