Problem with access to ListElement's proporty after delegate's function calling
-
wrote on 12 Jan 2020, 09:19 last edited by aha_1980 1 Dec 2020, 14:16
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.
-
wrote on 13 Jan 2020, 08:22 last edited by IntruderExcluder
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" } } } }
-
wrote on 12 Jan 2020, 10:41 last edited by
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
. -
wrote on 12 Jan 2020, 10:59 last edited by
Thanks for answer, IntruderExcluder.
I replaced
myModel.get(j).name = "byBottomButton"
to
myModel.setProperty(j, "name", "byBottomButton")
, but it still don't work right.. -
wrote on 13 Jan 2020, 08:22 last edited by IntruderExcluder
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" } } } }
-
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
. -
wrote on 13 Jan 2020, 10:21 last edited by
It really works!
Thank you, IntruderExcluder, GrecKo.
6/6