Сталкиваюсь иногда с некоторыми хитростями в 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
Кстати, вот документация на лэйауты: тынц.
Вот как-то так =)