Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access delegate properties in ListView using index

Tags:

qt5

qml

qtquick2

I want to access delegate properties in ListView. I've tried with contentItem but sometimes it's undefined.

Here is my code:

ListModel{
            id: modeldata
            ListElement{
                name:"don"
                rank:1
            }
            ListElement{
                name:"shan"
                rank:2
            }
            ListElement{
                name:"james"
                rank:3
            }
            ListElement{
                name:"jeggu"
                rank:4
            }
        }
        Component{
            id: delegateitem
            Row {
                property int count: rank
                Rectangle{
                    width: 100
                    height: 50
                    Text{
                        anchors.centerIn: parent
                        text: name
                    }
                }
            }
        }
        ListView{
            id: listview
            focus: true
            anchors.fill: parent
            model: modeldata
            delegate: delegateitem
            onCurrentIndexChanged: {
        console.log("position",currentIndex)
        console.log("property",contentItem.children[currentIndex].count);
            }
        }

Problem invalid output at position 1

qml: position 0
qml: property 1
qml: position 1
qml: property undefined
qml: position 2
qml: property 2
qml: position 3
qml: property 3
like image 802
Jeggu Avatar asked Mar 14 '23 03:03

Jeggu


1 Answers

@Teimpz didn't really explain it well. Especially since there are bunch of qt project and ubuntu touch qml examples and use cases where you manage dynamically created list elements using javascript, and that is why they have javascript methods and properties

In QML there is more a notion of parent than a child, which is common in html. In bigger projects it is recommended (as you can also see in qt examples and in docs http://doc.qt.io/qt-5/qtqml-javascript-expressions.html#functions-in-imported-javascript-files) to have js logic separate from qml elements so you do access and manage elements from outside rather than pollute you qml elements with js logic, but not in a way of looking for children elements, but rather exposing children elements that you need.

In your case you should just use currentItem, same as you use currentIndex, so currentItem.count will give you what you need. And if you don't need current item at all, you can access elements from model directly:

modelData.get(currentIndex).count, or listview.model.get(currentIndex).count

As for the hack that is mentioned by @Teimpz that is also one bad example. When you have more complex requirements and wanting specific elements inside delegate, every delegate has ListView.isCurrentItem property which you can attach and check. This would mean you can add property var myTargetItem to listview, and set it from child to whatever element you want if that delegate is current http://doc.qt.io/qt-5/qml-qtquick-listview.html#isCurrentItem-attached-prop

You can of course do that for any kind of event, maybe activeFocus so you could only reference activeFocused item.

This once again give you ability to expose only wanted elements without any advanced logic or lopping. Combining this with signals you can create very complex but clean interfaces without searching through children items.

So in the end maybe less nice but still better than searching for elements would be to add property int currentItemCount: 0 to listview. In delegate (Row element) you then add property bool isCurrentItem: ListView.isCurrentItem so you get onIsCurrentItemChanged signal inside delegate, where you can do: onIsCurrentItemChanged: if(isCurrentItem) listview.currentItemCount = count so you have your current item count always set

like image 126
Petar Avatar answered Apr 07 '23 06:04

Petar