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 ofMyDelegate
is binded toname
property, but not backwards (since there is no two-way bindings in QML), so settingtext
manually will not changename
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 ofListModel
. -
This is because your
text
property ofMyDelegate
is binded toname
property, but not backwards (since there is no two-way bindings in QML), so settingtext
manually will not changename
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" } } } }
-
@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 callsQAbstractItemModel::setData
.