ListView ContentItem Children Only Contains First Delegate
-
I'm trying to iterate over all the items added to a ListView (so that I can automatically set their anchors to be the full width of the parent and add margins to them), but for some reason it's only listing the first delegate that was added.
I'm using QT 6.7.0.
The following simple QML produces the issue. Does anyone know what's going on or how I can properly get all the elements added to the ListView?
import QtQuick import QtQuick.Controls ApplicationWindow { visible: true width: 400 height: 400 ListView { id: listView anchors.fill: parent spacing: 10 model: 10 delegate: Rectangle { objectName: "MyRect" + index height: 50 color: "lightblue" Text { anchors.centerIn: parent text: "Item " + index } } Component.onCompleted: { console.log(listView.contentItem.children); } } }
-
@KidTrent said in ListView ContentItem Children Only Contains First Delegate:
import QtQuick.Controls
It is only timing issue. All the delegate objects are not created immediately. Just add the following timer & you will get all the objects.
Timer { repeat: false running: true interval: 1000 onTriggered: { for(var i=0;i<listView.contentItem.children.length;i++){ console.log(" Child = "+i+" "+listView.contentItem.children[i].objectName) } } }
-
@dheerendra said in ListView ContentItem Children Only Contains First Delegate:
Timer {
repeat: false
running: true
interval: 1000
onTriggered: {
for(var i=0;i<listView.contentItem.children.length;i++){
console.log(" Child = "+i+" "+listView.contentItem.children[i].objectName)
}
}
}That's unfortunate, thanks.
@jeremy_k said in ListView ContentItem Children Only Contains First Delegate:
What's the purpose of listing children of the contentItem? Delegate instances are managed by the ListView, and may come and go.
So that I could modify the elements within ListView programmatically automatically with a custom ListView component, instead having to define them each time I use the component. In my specific case, I'm trying to add 10px of margins around each element for padding, but then on top of that the rightMargin needs 27px (10px + size of scrollbar, 17px) so that it does not overlap the scrollbar.
-
@KidTrent said in ListView ContentItem Children Only Contains First Delegate:
@jeremy_k said in ListView ContentItem Children Only Contains First Delegate:
What's the purpose of listing children of the contentItem? Delegate instances are managed by the ListView, and may come and go.
So that I could modify the elements within ListView programmatically automatically with a custom ListView component, [...]
Do that in the delegate.
-
@jeremy_k Yes, but I was trying to avoid doing that in the deligate so I don't have to remember to do it in every instance where I use the custom component... Right now I have to add margins: 10 and then rightMargin: 27 (17 from the scroll bar). Just trying to be less tedious... right now it's fine, but a year from now I might not remember why it's not working as expected.
-
@KidTrent said in ListView ContentItem Children Only Contains First Delegate:
@jeremy_k Yes, but I was trying to avoid doing that in the deligate so I don't have to remember to do it in every instance where I use the custom component
What does custom component mean in this context?
I don't understand how putting a margin in a delegate is more tedious that doing delegate instance manipulation in imperative javascript. If it's needed in several places, define a component that creates appropriate spacing, and use or derive from that.
-
I have already created said component... but unfortunately the only way I can find to correctly keep the scrollbar from overlapping the content of the ListView is to manually adjust each delimiter by changing its rightMargin to the size of the ScrollBar (+ any extra padding).
For example.... In the following code I want some padding between the content and the listview itself. However, if I just add margins, it overlaps the scrollbar... AND it overrides the native rightMargin found in AppScrollListView.qml... So I then have to remember to do margins: 10; rightMargin: 27; every time I do an instance of AppScrollListView that has padding.
AppScrollListView.qml
import QtQuick import QtQuick.Layouts import QtQuick.Controls ListView { property int scrollBarWidth: root.orientation == ListView.Horizontal ? (horizontalScrollBar.visible ? horizontalScrollBar.width : 0) : (verticalScrollBar.visible ? verticalScrollBar.width : 0); property int scrollBarHeight: root.orientation == ListView.Horizontal ? (horizontalScrollBar.visible ? horizontalScrollBar.height : 0) : (verticalScrollBar.visible ? verticalScrollBar.height : 0); id: root clip: true interactive: true boundsBehavior: Flickable.StopAtBounds orientation: ListView.Vertical ScrollBar.vertical: ScrollBar { id: verticalScrollBar policy: root.orientation == ListView.Horizontal ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn; } ScrollBar.horizontal: ScrollBar { id: horizontalScrollBar policy: root.orientation == ListView.Horizontal ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff; } // After scrollbar for assignment rightMargin: scrollBarWidth }
Main.qml
``` AppScrollListView { id: collectionMenuListView anchors.fill: parent spacing: 10 model: 10 delegate: Button { text: "Button " + index anchors.left: parent.left anchors.right: parent.right anchors.margins: 10 anchors.rightMargin: 27 } }
-
@KidTrent said in ListView ContentItem Children Only Contains First Delegate:
For example.... In the following code I want some padding between the content and the listview itself.
I don't know what differentiates the content and the listview itself, although that might not be important.
Main.qml
``` AppScrollListView { id: collectionMenuListView anchors.fill: parent spacing: 10 model: 10 delegate: Button { text: "Button " + index anchors.left: parent.left anchors.right: parent.right anchors.margins: 10 anchors.rightMargin: 27
Anchoring is the wrong way to go about laying out the top level delegate. The view creates instances and positions them in the contentItem. Delegates should say how large each item should be, not how to position them.
This is a simplified attempt to accomplish what I understand to be the goal. Note that the delegate is uninvolved in margin management, other than limiting itself to the contentItem width.
import QtQuick 2.15 import QtQuick.Controls 2.15 ListView { id: view model: 100 ScrollBar.vertical: ScrollBar { } spacing: 10 leftMargin: spacing rightMargin: leftMargin + ScrollBar.vertical.width contentWidth: width - leftMargin - rightMargin delegate: Rectangle { id: rect width: ListView.view.contentWidth height: 20 color: "blue" } }
Another option is to anchor the scrollbars outside of the view, eg ScrollBar.veritical: ScrollBar { anchors.left: parent.right }.
-
@jeremy_k said in ListView ContentItem Children Only Contains First Delegate:
@KidTrent said in ListView ContentItem Children Only Contains First Delegate:
For example.... In the following code I want some padding between the content and the listview itself.
I don't know what differentiates the content and the listview itself, although that might not be important.
Main.qml
``` AppScrollListView { id: collectionMenuListView anchors.fill: parent spacing: 10 model: 10 delegate: Button { text: "Button " + index anchors.left: parent.left anchors.right: parent.right anchors.margins: 10 anchors.rightMargin: 27
Anchoring is the wrong way to go about laying out the top level delegate. The view creates instances and positions them in the contentItem. Delegates should say how large each item should be, not how to position them.
This is a simplified attempt to accomplish what I understand to be the goal. Note that the delegate is uninvolved in margin management, other than limiting itself to the contentItem width.
import QtQuick 2.15 import QtQuick.Controls 2.15 ListView { id: view model: 100 ScrollBar.vertical: ScrollBar { } spacing: 10 leftMargin: spacing rightMargin: leftMargin + ScrollBar.vertical.width contentWidth: width - leftMargin - rightMargin delegate: Rectangle { id: rect width: ListView.view.contentWidth height: 20 color: "blue" } }
Another option is to anchor the scrollbars outside of the view, eg ScrollBar.veritical: ScrollBar { anchors.left: parent.right }.
Thank you! The "contentWidth" assignment produces my expectation of how it would work. Sorry it took so long for me to reply, I've been sick the last week.
-