'QML List of Lists (2D data)
Summary: How can I nest one ListView inside another, feeding data from the outer model to an inner model inside the delegate?
Data and Desire
I have an array of arrays of data in JS:
[[ {t:0, label:"Big Bang"}, {t:5, label:"Earth Forms"} ],
[ {t:0, label:"Alternate Bang"}, {t:3, label:"Cool Stuff"} ],
[ {t:1, label:"Late Bang"}, {t:4, label:"Whee"}, {t:5, label:"More" } ]]
I want to display this as a horizontal-scrolling "timeline", where the top-level array represents rows of data and each sub-array represents items within that row, placed at various times.
Note that the timeline is only discrete at the millisecond level, with values out to the hour range. Unlike what this Excel-based mockup shows, a 2D grid of merged cells would be infeasible.
Code and Problem
I'm passing the array to a ListView
via a custom ListModel
:
Item {
property var timeline: []
onTimelineChanged: {
rowData.clear();
timeline.forEach(function(evts){
rowData.append({ events:evts });
});
}
ListView {
id: rows
model: ListModel { id:rowData }
delegate: Item {
Text { text: "Idx #"+index }
ListView {
orientation: ListView.Horizontal
model: ListModel { id:events }
delegate: …
}
}
}
}
This is populating the rows properly, but I cannot figure out how to pass the events
data role from the outer ListView
into the events
model within each delegate.
Additionally, as I wrote this question up, I realized that each row may try to scroll horizontally independent of one another. I want them all to scroll as a group. This makes me wonder if nested ListView
is the appropriate tool for this job, or if I should be using some other data-driven QML structure.
Solution 1:[1]
You can simply assign events
to the inner ListView.model
, for example:
ListView {
anchors.fill: parent
model: ListModel { id:rowData }
delegate: Rectangle {
width: parent.width; height: 50
ListView {
anchors.fill: parent; orientation: ListView.Horizontal
model: events
delegate: Item {
width: 80; height: 20
Text { text: label }
}
}
}
}
When a JavaScript array is appended to a ListModel
row, it will be automatically converted to a ListModel
(however, Qt documentation says nothing about this). So when you access the role name events
in the delegate in the outer ListView
, what you get is something like this:
ListModel { //row 0
id: events
ListElement {t:0, label:"Big Bang"}
ListElement {t:5, label:"Earth Forms"}
}
And I think it's fine to horizontally scroll all inner ListView
at the same time by setting contentX
or positionViewAtIndex
to all inner ListView
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | mcchu |