Как создать многоуровневую компоновку жидкости в QML

Я разработал макет в QML, чтобы узнать больше о его функциях и задать несколько вопросов о "лучших практиках" при разработке такого макета. Вот это:

enter image description here

Это по сути ColumnLayout состояла из трех RowLayouts, каждый с некоторыми прямоугольникs. Размер каждой строки и прямоугольника должен быть вычислен, например:

  • первая строка: высота = 40%, ширина = Сто%
    • красный прямоугольник, заполняющий всю область
  • второй ряд: высота = 20%, ширина = 100%
    • темно-зеленый прямоугольник: высота = 100%, ширина = 20%,
    • светло-зеленый прямоугольник: высота = 100%, ширина = 80%
  • третий ряд: высота = 40%, ширина = 100%
    • темно-синий прямоугольник: высота = 100%, ширина = 40%,
    • Синий Прямоугольник: Высота = 100%, Ширина = 20%
    • светло-голубой прямоугольник: высота = 100%, ширина = 40%

QML, который я придумал, работает и находится в следующем. У меня есть несколько вопросов по этому поводу:

  1. я установил процент ширины и высоты, используя макет.preferredHeight: X * родитель.высота узор. Другие опции вызвали некоторые проблемы (например, preferredHeight вызвал предупреждения цикла привязки). Мой верный подход и эффективно?
  2. как хак, я установил макет.fillWidth: true для первого элемента строки #2 и строки #3, что для меня не имеет смысла, но работает. Если я установлю их ширину в процентах (например,макет.preferredWidth: 0.2*родитель.ширина) их строка свернется до ширины 0. Это ожидаемое поведение? Есть ли лучшее решение?
  3. у вас есть какие-либо рекомендации на макеты? Я на правильном пути?

вот мой Код QML для макета:

ApplicationWindow {
    x: 500
    y: 100
    width: 250
    height: 150
    visible: true

    ColumnLayout {
        anchors.fill: parent
        spacing: 0
        RowLayout {
            spacing: 0
            Layout.preferredHeight: 0.4*parent.height
            Layout.fillHeight: false
            Rectangle {
                Layout.fillHeight: true
                Layout.fillWidth: true
                color: "red"
            }
        }
        RowLayout {
            spacing: 0
            Layout.preferredHeight: 0.2*parent.height
            Layout.fillHeight: false
            Rectangle {
                Layout.fillHeight: true
                Layout.fillWidth: true
                color: "darkGreen"
            }
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 0.8*parent.width
                color: "lightGreen"
            }
        }
        RowLayout {
            spacing: 0
            Layout.preferredHeight: 0.4*parent.height
            Layout.fillHeight: false
            Rectangle {
                Layout.fillHeight: true
                Layout.fillWidth: true
                color: "darkBlue"
            }
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 0.2*parent.width
                color: "blue"
            }
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 0.4*parent.width
                color: "lightBlue"
            }
        }
    }
}

обновление:

мой подход кажется более хакерским, чем я ожидал:

  1. положить текст элементов, так как дети в этом макете поднимает привязка цикла предупреждения типа:

QML QQuickLayoutAttached: обнаружен цикл привязки для свойства "preferredWidth"

если текст обертки внутри прямоугольник предупреждения исчезнуть.

  1. на интервал: 0 кажется, играет важную роль. Опущение этого вызовет предупреждения цикла привязки.

хотя мой подход к дизайну компоновки fluid в QML работает, он имеет некоторые серьезные проблемы и может не подпадать под "лучшие практики".

2 ответов


наш QtQuick.Макет не дает никаких реальных улучшений по сравнению с классической системой крепления. Я бы рекомендовал избегать их. Вы можете иметь больше контроля над своим макетом, используя якоря.

вот тот же самый дизайн без QtQuick.Макет:

ApplicationWindow {
    x: 500
    y: 100
    width: 250
    height: 150
    visible: true

    Column {
        anchors.fill: parent

        Row {
            anchors.left: parent.left
            anchors.right: parent.right
            height: 0.4 * parent.height

            Rectangle {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: parent.width
                color: "red"
            }
        }

        Row {
            anchors.left: parent.left
            anchors.right: parent.right
            height: 0.2 * parent.height

            Rectangle {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: 0.2 * parent.width
                color: "darkGreen"
            }

            Rectangle {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: 0.8 * parent.width
                color: "lightGreen"
            }
        }

        Row {
            anchors.left: parent.left
            anchors.right: parent.right
            height: 0.4 * parent.height

            Rectangle {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: 0.4 * parent.width
                color: "darkBlue"
            }
            Rectangle {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: 0.2 * parent.width
                color: "blue"
            }
            Rectangle {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: 0.4 * parent.width
                color: "lightBlue"
            }
        }
    }
}

до сих пор я никогда не встречал никакого дизайна, который невозможно было бы сделать без QtQuick.Макет.


запрещено (и ненужно) пытаться ссылаться на ширину и высоту родителя из элементов внутри макета.

, когда fillWidth (или fillHeight) установлено значение true, то элементы выделяются пространство пропорционально их указанным preferredWidth (или preferredHeight).

поэтому правильный способ создания макета заключается в следующем. Я изменил внешний вид только для того, чтобы показать, что интервал и Text смогите также быть установлено свободно как пожелано. Без привязки петли.

ApplicationWindow {
    x: 500
    y: 100
    width: 250
    height: 150
    visible: true

    ColumnLayout {
        anchors.fill: parent
        spacing: 5
        RowLayout {
            spacing: 5
            Layout.preferredHeight: 40
            Layout.fillHeight: true
            Rectangle {
                Layout.fillHeight: true
                Layout.fillWidth: true
                color: "red"
            }
        }
        RowLayout {
            spacing: 5
            Layout.preferredHeight: 20
            Layout.fillHeight: true
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 20
                Layout.fillWidth: true
                color: "darkGreen"
            }
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 80
                Layout.fillWidth: true
                color: "lightGreen"
            }
        }
        RowLayout {
            spacing: 5
            Layout.preferredHeight: 40
            Layout.fillHeight: true
            Text {
                Layout.fillHeight: true
                Layout.preferredWidth: 40
                Layout.fillWidth: true
                color: "darkBlue"
                text: "hello world!"
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
            }
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 20
                Layout.fillWidth: true
                color: "blue"
            }
            Rectangle {
                Layout.fillHeight: true
                Layout.preferredWidth: 40
                Layout.fillWidth: true
                color: "lightBlue"
            }
        }
    }
}