Как я могу использовать макеты QML, чтобы упорядочить масштабированные элементы с соотношением сторон в сетке?
У меня есть прямоугольники с определенным соотношением сторон и прямоугольники с обратным соотношением сторон. Я хотел бы расположить их в сетке по своему выбору (наоборот, не обязательно должна быть регулярная сетка: я бы предпочел решение, в котором я могу построить RowLayout
с и ColumnLayout
по желанию).
Я знаю, что могу иметь масштабируемые элементы в моих макетах, используя Layout.fillHeight
а также Layout.fillWidth
, К сожалению, я не могу найти способ правильно определить пропорции для моего Rectangle
s. Я знаю QML Image
может сделать это (через его fillMode
собственность), но я не вижу простого способа сделать это красиво.
Любая помощь или указатели в правильном направлении будет высоко ценится!
Заметьте, я предполагаю, что QML Layouts - это то, что нужно, но если есть функциональное решение с использованием только якорей или простого Row
/Column
настройка, я все для этого!
Также обратите внимание, что я предпочел бы сохранить площадь двух типов Rectangle
то же самое, как кажется при экспериментировании, это не так тривиально...
РЕДАКТИРОВАТЬ
Попытка того, что я имею в виду, за вычетом ограничения равной площади. Прямоугольники заполняют ширину, но оставляют пространство в высоте, потому что они ограничены их соотношением сторон и заполненной шириной. То же самое относится и к высоте, но мне не удается объединить их.
3 ответа
В течение нескольких дней я боролся за правильный способ сделать это. Я не смог найти ни одного рабочего примера, поэтому я написал свой собственный.
Этот прямоугольник всегда будет уважать его направленное отношение и сохранит свои поля. Хитрость заключается в том, чтобы относиться к разным случаям: либо соотношение родителей больше, чем намеченное, либо нет. В одном случае вы привязываете ширину к родителю и устанавливаете высоту в соответствии с. В другом случае вы делаете это по-другому.
Rectangle {
color : 'green'
// INPUTS
property double rightMargin : 20
property double bottomMargin : 20
property double leftMargin : 20
property double topMargin : 20
property double aimedRatio : 3/4
// SIZING
property double availableWidth : parent.width - rightMargin - leftMargin
property double availableHeight : parent.height - bottomMargin - topMargin
property bool parentIsLarge : parentRatio > aimedRatio
property double parentRatio : availableHeight / availableWidth
height : parentIsLarge ? width * aimedRatio : availableHeight
width : parentIsLarge ? availableWidth : height / aimedRatio
anchors.top : parent.top
anchors.topMargin : topMargin
anchors.left : parent.left
anchors.leftMargin : leftMargin
}
Надеюсь, это поможет людям, которые приезжают сюда с поиском Google!
Я поддержал ответ @CharlesSALA (потому что он работает!), Но подумал, что также предложу альтернативный ответ на основе макетов.
В
AspectItem
отвечает за обеспечение правильного поля для поддержания ширины, используя
implicitWidth
. В
Layout
отвечает за обеспечение правильного поля для поддержания высоты, используя
Layout.maximumHeight
.
То же самое будет работать в
GridLayout
вместо
ColumnLayout
&
RowLayout
. Результат немного отличается, потому что столбцы должны оставаться выровненными во всех строках, но в обоих случаях соотношение сторон прямоугольников сохраняется, как требуется.
AspectItem.qml
import QtQuick 2.11
Item {
id: container
property real aimedRatio: 3/4
property alias color: content.color
implicitWidth: height*container.aimedRatio
implicitHeight: width/container.aimedRatio
Rectangle {
id: content
anchors.horizontalCenter: container.horizontalCenter
height: container.height
implicitWidth: height*container.aimedRatio
}
}
main.qml
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
ApplicationWindow {
id: window
visible: true
width: 800
height: 800
y: 0
ColumnLayout {
anchors.fill: parent
RowLayout {
width: parent.width
AspectItem {
color: "darkseagreen"
aimedRatio: 1/2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
AspectItem {
color: "seagreen"
aimedRatio: 2/1
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
AspectItem {
color: "lightseagreen"
aimedRatio: 1/2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
}
RowLayout {
width: parent.width
AspectItem {
color: "darkcyan"
aimedRatio: 2/1
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
AspectItem {
color: "cyan"
aimedRatio: 1/2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
AspectItem {
color: "lightcyan"
aimedRatio: 2/1
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
}
RowLayout {
width: parent.width
AspectItem {
color: "darksalmon"
aimedRatio: 1/2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
AspectItem {
color: "salmon"
aimedRatio: 2/1
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
AspectItem {
color: "lightsalmon"
aimedRatio: 1/2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: implicitHeight
}
}
}
}
Результат
При запуске:
Растянутые узкие:
Широко растянуты:
Вы можете использовать привязку свойств, чтобы связать width
прямоугольника с height
используя соотношение сторон следующим образом,
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
Window {
id: root
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property int minWidth: 150
property int maxWidth: 300
property int minHeight: 150
property int maxHeight: 250
property int rowWidth: root.width/3 //Change accordingly the width of each child item w.r.t. the width of the root.
Row {
id: layout
anchors.fill: parent
spacing: 6
Rectangle {
color: 'red'
// 4/3 is the aspect ratio of the first Rectangle
height: (3*width/4)<root.minHeight ? root.minHeight : ( (3*width/4)>root.maxHeight ? root.maxHeight : 3*width/4 )
width: (root.rowWidth) < root.minWidth ? root.minWidth : ( root.rowWidth > root.maxWidth ? root.maxWidth : root.rowWidth)
Text {
anchors.centerIn: parent
text: parent.width + 'x' + parent.height
}
}
Rectangle {
color: 'green'
// 3/4 is the aspect ratio of the second Rectangle
height: (4*width/3)<root.minHeight ? root.minHeight : ( (4*width/3)>root.maxHeight ? root.maxHeight : 4*width/3 )
width: (root.rowWidth) < root.minWidth ? root.minWidth : ( root.rowWidth > root.maxWidth ? root.maxWidth : root.rowWidth)
Text {
anchors.centerIn: parent
text: parent.width + 'x' + parent.height
}
}
}
}