Solved qml ListView delegate containing a Loader doesn't expand when loading some components?
-
Hi,
I've a ListView using a delagate that is aColumn
with first aRectangle { id: firstLine }
and under aLoader { id: childView }
that is not loaded.There is a checkabe Button in
firsLine
that is suppose to load / unload a Component in the Loader. Here is its code:onClicked: { if (checked) { childView.sourceComponent = myComponent; childView.height = 100; } else { childView.sourceComponent = undefined; childView.height = 0; } }
So the idea is to simulate a
TreeView
inside my ListView and being able to dynamically expand my rows using the Delegate.If I use a simple Text Delegate like this:
Component { id: myComponent Text { text: modelIndex } }
It is working as expected. cf the number the modelIndex with extra space under each row.
BUT of course I'm loading a more complex component (another ListView) and it is not working :'(
Basically the row is not expanding and the Component loaded is drawn on top of thefirstLine
Rectangle.I've this behaviour if I just encapsulate the component above in an item like this:
Component { id: myComponent // Text { text: modelIndex } Item { // height: 100 // width: parent.width Text { // height: 100 text: modelIndex } //okay } }
Any idea why?
Edit: I don't have this issue if I don't use the
Loader
but instead directly define mychildView
and play on it'svisible
attribute in the expand button.
I don't understand why it is not working dynamically with a Loader... It will allow to have some kind of easy loading for the child view and performance will improve -
@mbruel AFAIK the loader superimposes its own hight and width on the component it loads.
change the loader hight and it should work.The fact that you see it "working" with a text element is not surprising, text is drawn outside the boundaries of the TextElement without a problem (is the default)
-
@J-Hilk well in my JS function I change the height of the Loader. I even tried to change the one of its item but it doesn't do anything.
And why is the Loader painted on top of myfirstLine
although my Delegate is a Column? -
@mbruel it's hard for me to understand the issue at hand,
can you share the example you quoted? Seems like a small enough project, could clarify things :D
-
@J-Hilk arf I thought I could avoid doing a small example and just manage to describe it...
sure it will be easier with a small use case. Ok I'll do that after lunch ;) -
So thanks to @LeLev who gave me a solution using a
ColumnLayout
, here is from where I was startingListView{ anchors.fill: parent spacing: 10 model: 5 delegate: Column { width: parent.width height: exp.checked ? r.height + v.height + spacing : r.height spacing: 10 Rectangle{ id: r width: parent.width height: 50 color: "grey" CheckBox{ id:exp anchors.right: parent.right text: "expand " + index } } ListView { id: v model: 10 spacing: 1 clip : true height: contentHeight width: parent.width visible: exp.checked delegate: Rectangle{ height: 30 width: parent.width color: "lightblue" } } } }
The goal was to dynamically load the second
ListView
inLoader
so the page loads much faster.Here is @LeLev solution using a
ColumnLayout
:// 2.: Solution with a ColumnLayout Component{ id:view ListView { model: 10 spacing: 1 clip : true height: contentHeight delegate: Rectangle{ height: 30 width: parent.width color: "lightblue" } } } ListView{ anchors.fill: parent spacing: 10 model: 5 delegate: ColumnLayout{ height: exp.checked ? 50 + l.item.contentHeight : 50 width: root.width spacing: 1 Rectangle{ Layout.fillHeight: true Layout.fillWidth: true Layout.preferredHeight: 50 Layout.maximumHeight: 50 color: "grey" CheckBox{ id:exp anchors.right: parent.right text: "expand " + index onCheckedChanged: { l.sourceComponent = checked ? view : undefined } } } Loader{ id:l Layout.fillHeight: sourceComponent != undefined Layout.fillWidth: true // Layout.preferredHeight: sourceComponent != undefined ? 100 : 0 } } }
and finally after a break and fighting with
Column
, it is also working without aLayout
:)// 3.: Solution with a Column Component{ id:view ListView { model: 10 spacing: 1 clip : true height: contentHeight width: root.width delegate: Rectangle{ height: 30 width: parent.width color: "lightblue" } } } ListView{ anchors.fill: parent spacing: 10 model: 5 delegate: Column{ width: parent.width height: exp.checked ? r.height + l.item.height + spacing : r.height spacing: 10 Rectangle{ id: r width: parent.width height: 50 color: "grey" CheckBox{ id:exp anchors.right: parent.right text: "expand " + index onCheckedChanged: { l.sourceComponent = checked ? view : undefined } } } Loader{ id:l } } }