Сталкиваюсь иногда с некоторыми хитростями в 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

Кстати, вот документация на лэйауты: тынц.

Вот как-то так =)

Leave a Comment

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

You may also like