Unsolved Dynamic creation/deletion of delegates inside delegates of ListView
-
Hi,
I am currently working on a view that uses a ListView to display data. Let's call the ListView mainLog. The delegates in mainLog are typically collapsed and just show an overview of the item. When the user clicks on the delegate it expands and show details of the item. The items of mainLog itself contain another list of data items which might be quite long. Let's call this list itemData. Currently I am doing this with a Repeater but since a Repeater always instantiates all of its delegate this might have bad performance.
My question now is: Is there a nice way to automatically (or manually) create and delete the visible delegates of itemData when scrolling the list of mainLog?
Cheers Heiko
-
Did you a get a chance to look at expanding delegate example in the example directory ?
quick/views/views.qml -
Well I know how to make an expandable delegate. The problem is how to handle other delegates inside there efficiently. Here is some example code to demonstrate what I have. I already thought one solution might be to use a TreeView with one nesting, restyle it to show a plain list and switch delegates... But I am not sure if the TreeView works with delegates of different size and I would rather work with less restructuring. Maybe there is something different.
Here is some example code to show what I mean:
import QtQuick 2.11 import QtQuick.Window 2.11 Window { visible: true width: 640 height: 480 property int size: 1000 title: qsTr("Hello World") ListModel { id: mainLogModel ListElement { title: "This is the first Entry" itemData: [ ListElement { detail: "Detail 1 of first Entry" }, ListElement { detail: "Detail 2 of first Entry" } ] } ListElement { title: "This is the second Entry" itemData: [ ListElement { detail: "Detail 1 of second Entry" } ] } } ListView { id: listView anchors.fill: parent model: mainLogModel delegate: Column { id: delegateColumn width: listView.width height: titleText.height Text { id: titleText text: title MouseArea { anchors.fill: parent onClicked: delegateColumn.state = delegateColumn.state !== "" ? delegateColumn.state = "" : delegateColumn.state = "open" } } Column { id: detailsItem visible: false Repeater { id: repeater delegate: Rectangle { x: 10 width: listView.width height: text.height color: "lightblue" Text { id: text text: detail } } } } states: State { name: "open" PropertyChanges { target: delegateColumn height: titleText.height + detailsItem.height } PropertyChanges { target: detailsItem visible: true } PropertyChanges { target: repeater model: itemData } } } } Component.onCompleted: { for (var i = 0; i < size; i++) { var details = []; for (var j = 0; j < size; j++) { details.push({"detail" : "Detail " + j + " of " + i + " Entry"}); } mainLogModel.append({"title": "This is " + i + " Entry", "itemData" : details}); } } }
The question is how I can enable the part with the repeater to only construct its delegates when they are visible. Like is done by the surrounding ListView. As you can see I already have some optimization by only setting the itemData model once an entry is opened. Otherwise this example would already be unbearably slow.