Сталкиваюсь иногда с некоторыми хитростями в QML, о которых, по всей видимости, приходится только догадываться, ибо то ли я проглядел это в документации, то ли этого действительно в ней не указано.
Так вот, задача: нужно три колонки одинаковой ширины.
Делаем:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("QMLTips&Tricks24")
RowLayout {
anchors.fill: parent
spacing: 0
Rectangle {
color: "blue"
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle {
color: "orange"
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle{
color: "green"
Layout.fillHeight: true
Layout.fillWidth: true
}
}
}
Соответственно на выходе получаем:

Получилось как и задумывали.
Обновим задачу: Оранжевая колонка должна иметь предпочтительную ширину 200 пикселей.
Делаем:
Rectangle {
color: "orange"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 200
}
Получаем:

Что-то не то, да..?
Вот тут начинается самое интересное.
Дело в том, что Layout.prefferedWidth (а так же Layout.minimumWidth) управляет пропорционально шириной относительно соседей, когда задано Layout.fillWidth: true
Соответственно что бы поведение пришло в норму, мы должны у соседей — синего и зелёного прямоугольника то же прописать желаемую ширину.
Делаем:
Rectangle {
color: "blue"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 200
}
Rectangle {
color: "orange"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 200
}
Rectangle{
color: "green"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 200
}
Получаем:

То есть как и задумывали, три одинаковые колонки.
Теперь наглядный пример насчёт пропорционально соседям изменяемости размеров. Если мы у синего прямоугольника зададим желаемую ширину в 50, а у зелёного 100, то соответственно синий будет в 4 раза меньше оранжевого (200/50=4), а зелёный буде в два раза меньше оранжевого (200/100=2).
То есть родитель Layout (RowLayout/ColumnLayout/GridLayout) берёт от потомков наибольший желаемый размер и относительно него пропорционально выставляет ширину всем потомкам.
Повторюсь, что так QML себя ведёт, только когда задано Layout.fillWidth: true
Делаем:
Rectangle {
color: "blue"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 50
}
Rectangle {
color: "orange"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 200
}
Rectangle{
color: "green"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: 100
}
Получаем:

Короче, считаем, что при указании preferredWidth, minimumWidth мы работаем с пропорциями относительно остальных в одном контейнере и всё.
Почему именно так, а не иначе?
По-моему как раз для того, что бы можно было задать поведение при растягивании/сжимании…
Аналогичная ситуация произойдёт, если мы оранжевой колонке захотим указать minimumWidth: 100 при fillWidth:true
Что делать, если нужно, что бы все колонки имели одинаковую ширину и заполняли всё пространство (т.е. fillWidth: true), но при этом у них (у всех или у некоторых) должна быть задана разная минимальная ширина?
Я в таком случае прописываю у всех: preferredWidth наибольшее из minimumWidth. Но стоит учитывать, что при приближении к минимальному значению размер изменяется пропорционально.
Надеюсь, теперь больше с этим проблем не возникнет.
Кстати, такое же поведение будет если у компонента задано свойство implicitWidth или implicitHeight, потому что если мы не задали явно Layout.preferredWidth или Layout.fillHeight, то берутся как раз они. Наверное вы спрашиваете: как быть, если это не просто прямоугольник, а какой-то компонент? То всё просто — оберните его в Item или Rectangle или задайте явно Layout.preferredWidth
Кстати, вот документация на лэйауты: тынц.
Вот как-то так =)
