Как я могу использовать макеты QML, чтобы упорядочить масштабированные элементы с соотношением сторон в сетке?

У меня есть прямоугольники с определенным соотношением сторон и прямоугольники с обратным соотношением сторон. Я хотел бы расположить их в сетке по своему выбору (наоборот, не обязательно должна быть регулярная сетка: я бы предпочел решение, в котором я могу построить RowLayoutс и ColumnLayoutпо желанию).

Я знаю, что могу иметь масштабируемые элементы в моих макетах, используя Layout.fillHeight а также Layout.fillWidth, К сожалению, я не могу найти способ правильно определить пропорции для моего Rectangles. Я знаю QML Image может сделать это (через его fillMode собственность), но я не вижу простого способа сделать это красиво.

Любая помощь или указатели в правильном направлении будет высоко ценится!

Заметьте, я предполагаю, что QML Layouts - это то, что нужно, но если есть функциональное решение с использованием только якорей или простого Row/Column настройка, я все для этого!

Также обратите внимание, что я предпочел бы сохранить площадь двух типов Rectangle то же самое, как кажется при экспериментировании, это не так тривиально...

РЕДАКТИРОВАТЬ

Попытка того, что я имею в виду, за вычетом ограничения равной площади. Прямоугольники заполняют ширину, но оставляют пространство в высоте, потому что они ограничены их соотношением сторон и заполненной шириной. То же самое относится и к высоте, но мне не удается объединить их.

1

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
            }
        }
    }
}
Другие вопросы по тегам