I'm trying to build a custom control where I can place other controls (Button
s, Slider
s, edit fields, etc.) grouped together.
The control should appear on the right side of the window and should have a fixed width
of 200
. This works fine:
RowLayout {
Item {
Layout.fillWidth: true
}
MyControl {
Layout.fillHeight: true
Layout.preferredWidth: 200
}
}
Now, the problem is with the layouts and controls I used inside MyControl
.
I'm using a Rectangle
with a ColumnControl
in it and in the ColumnControl
nested the GroupBoxes (see code below).
In one of the GroupBox
es I want to place several Button
s in a row, so I am using a RowLayout
(I tried Row
also, same result). If I only put two or three Button
s in a row, the Button
s get stretched to fill the entire width and everything is fine. But when I use more Button
s, they are not shrunk below a certain size. Instead, the RowLayout
grows to the right and some of the Button
s are not visible since they are positioned outside the window.
It seems that the RowLayout
calculates the size of its children first and then resizes itself. Now what I want is that the RowLayout
is fixed to the parent width
and the children are shrunk to fit into the parent.
I managed to do that with a workaround, but I'm not happy with that. There must be a more elegant way. I also tried to set the width
of the RowLayout
to the parent.width
but got binding loops. Everything looked fine, but I don't want to write code which starts with a couple of warnings.
Here's the code of the control:
Rectangle {
id: rootRect
ColumnLayout {
anchors.fill: parent
spacing: 4
GroupBox {
Layout.fillWidth: true
title: "GroupBox Title"
RowLayout {
id: buttonGroupWithWorkaround
enabled: false
anchors.fill: parent
//the workaround:
property int numberOfButtons: 6
property int buttonWidth: (rootRect.width - 2 * buttonGroupWithWorkaround.spacing) / numberOfButtons - buttonGroupWithWorkaround.spacing
Button {
Layout.preferredWidth: buttonGroupWithWorkaround.buttonWidth
text: "|<"
}
Button {
Layout.preferredWidth: buttonGroupWithWorkaround.buttonWidth
text: "<<"
}
Button {
Layout.preferredWidth: buttonGroupWithWorkaround.buttonWidth
text: "<"
}
Button {
Layout.preferredWidth: buttonGroupWithWorkaround.buttonWidth
text: ">"
}
Button {
Layout.preferredWidth: buttonGroupWithWorkaround.buttonWidth
text: ">>"
}
Button {
Layout.preferredWidth: buttonGroupWithWorkaround.buttonWidth
text: ">|"
}
}
}
GroupBox {
Layout.fillWidth: true
title: "NextGroupBox Title"
RowLayout {
id: theButtonGroup
enabled: false
anchors.fill: parent
Button {
//this doesn't work
Layout.fillWidth: true
text: "|<"
}
Button {
Layout.fillWidth: true
text: "<<"
}
Button {
Layout.fillWidth: true
text: "<"
}
Button {
Layout.fillWidth: true
text: ">"
}
Button {
Layout.fillWidth: true
text: ">>"
}
Button {
Layout.fillWidth: true
text: ">|"
}
}
}
GroupBox {
Layout.fillWidth: true
title: "OtherGroupBox Title"
//some other controls
}
}
}
Sizing can be sometimes a little bit tricky.
fillWidth
ensures that the Button
s grow or shrink to fill the available space. However, this behaviour is not arbitrary. It follows other constraints set on the Item
. In particular, the size is never shrunk under the implicitWidth
of the Item
.
Hence, in this case you can solve the issue by setting a smaller implicitWidth
, like this:
Button {
Layout.fillWidth: true
text: ">"
implicitWidth: 20 // the minimum width will be 20!
}
Alternatively you can define a custom ButtonStyle
which defines a well-sized label
but it really sounds overkilling in this specific case.
Have also a look at this answer (or other resources on SO) to have a better grasp about layouts/sizing.