MyTetra Share
Делитесь знаниями!
Особенности расчета ширины элементов в RowLayout
Время создания: 14.09.2022 13:25
Автор: PavelK
Текстовые метки: qt, QML, RowLayout, ширина, элемент, размещение
Раздел: Компьютер - Программирование - Язык C++ (Си++) - Библиотека Qt - QML
Запись: xintrea/mytetra_syncro/master/base/1663151143r180n8m255/text.html на raw.github.com

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

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования