问题
I've set up a file called test1.qml with the following contents:
import QtQuick 2.6
import QtQuick.Layouts 1.3
Rectangle {
width: 800; height: 1000;
ColumnLayout {
anchors.centerIn: parent
// Header goes here
Repeater {
model: 3
delegate: MyRectangle {
width: 150
height: width
color: "#44ff0000"
}
}
// Footer goes here
}
}
I've also setup a file called test2.qml defined as follows:
import QtQuick 2.6
import QtQuick.Layouts 1.3
Rectangle {
width: 800; height: 1000;
ColumnLayout {
anchors.centerIn: parent
// Header goes here
Repeater {
model: 3
delegate: Column {
MyRectangle {
width: 150
height: width
color: "#44ff0000"
}
}
}
// Footer goes here
}
}
Finally, MyRectangle.qml has the following contents:
import QtQuick 2.6
Rectangle {
MouseArea {
anchors.fill: parent
onClicked: {
parent.height += 50
}
}
}
My goal is that when instances of MyRectangle are clicked, their heights change, and the ColumnLayout should enlarge so that the items maintain their spacing.
When I run test.qml, the result is not what I expect, in that the instances of MyRectangle overlap each other as they are clicked. However, test2.qml gives the desired behavior, and the instances of MyRectangle maintain their spacing as the ColumnLayout enlarges.
At the request of derM, I think the GIFs below may help to explain this more clearly.
The (undesired) behavior of test1.qml:
The (desired) behavior of test2.qml:
Why is it that I have to wrap the objects in a Column to achieve the desired result?
回答1:
The reason might sound strange:
The [...]Layout
-family is not just there to arrange the objects, but also to resize them. You are not supposed to set or alter sizes in it.
To do its job, when you don't use the available attached properties to set the sizes, it will use the implicitWidth/Height
of your Item
s.
If you have not set implicit dimension, uppon adding new items to the layout, their implicit dimensions will be set to be equal to their set dimsions. But this is not a binding! So if you now update the height
, the implicitHeight
will stay at the original size, thus the Layout won't react to the change.
If you add the Column
to your delegate, things change: The Column
updates its implicitHeight
in accordeance to the bounding rectangle of its children. If you now resize the Rectangle
s height, the Column
will adapt the implicitHeight
and the Layout
will react to the change.
Now you have the following solutions:
- Use the
Layout
attached property, to set and change the size hints. - Use the delegates
implicitHeight
instead of theheight
. This might be semantically wrong though. - Don't use the
ColumnLayout
but just a regularColumn
when you don't need the additional layouting capatibilities (the attached properties and resizing of the Items and so on), which seems to be the case in your problem.
Column {
anchors.centerIn: parent
spacing: 5
// Header goes here
Repeater {
model: 3
delegate:
Rectangle {
width: 150
height: width
color: "#44ff0000"
MouseArea {
anchors.fill: parent
onClicked: {
console.log(parent.implicitHeight)
parent.height += 50
}
}
}
}
// Footer goes here
}
来源:https://stackoverflow.com/questions/47363160/adjust-columnlayout-when-a-repeaters-delegate-height-changes