Отрегулируйте ColumnLayout при изменении высоты делегата повторителя

Я создал файл test1.qml со следующим содержимым:

import QtQuick 2.6
import QtQuick.Layouts 1.3

Rectangle {
    width: 800; height: 1000;

    ColumnLayout {
        anchors.centerIn: parent

        // Header goes here

        Repeater {
            model: 3
            delegate: MyRectangle {
                width: 150
                height: width
                color: "#44ff0000"
            }
        }

        // Footer goes here

    }
}

Я также настроил файл с именем test2.qml, определенный следующим образом:

import QtQuick 2.6
import QtQuick.Layouts 1.3

Rectangle {
    width: 800; height: 1000;

    ColumnLayout {
        anchors.centerIn: parent

        // Header goes here

        Repeater {
            model: 3
            delegate: Column {
                MyRectangle {
                    width: 150
                    height: width
                    color: "#44ff0000"
                }
            }
        }

        // Footer goes here

    }
}

Наконец, MyRectangle.qml имеет следующее содержимое:

import QtQuick 2.6

Rectangle {
    MouseArea {
        anchors.fill: parent
        onClicked: {
            parent.height += 50
        }
    }
}

Моя цель состоит в том, чтобы при щелчке экземпляров MyRectangle их высота изменялась, а ColumnLayout увеличивался, чтобы между элементами сохранялся их интервал.

Когда я запускаю test.qml, результат оказывается не таким, как я ожидал, поскольку экземпляры MyRectangle перекрывают друг друга при щелчке. Однако test2.qml дает желаемое поведение, а экземпляры MyRectangle сохраняют свои интервалы по мере увеличения ColumnLayout.

По просьбе derM я думаю, что приведенные ниже GIF-файлы могут помочь объяснить это более четко.

(Нежелательное) поведение test1.qml:

(Нежелательное) поведение **test1.qml**

(Желаемое) поведение test2.qml:

(Желаемое) поведение **test2.qml**

Почему мне приходится заключать объекты в столбец для достижения желаемого результата?


person Knute Knudsen    schedule 18.11.2017    source источник
comment
Ретранслятор не имеет макета. Зачем вам использовать Column или RowLayout в качестве делегата, если у вас есть только один дочерний элемент внутри них?   -  person derM    schedule 18.11.2017
comment
Повторитель просто создает несколько экземпляров делегата, возможно, передавая данные модели для каждого экземпляра. Макет может быть применен извне, имея повторитель внутри макета, к которому будут привязаны делегаты, или каждый делегат может заботиться о своем собственном позиционировании, например, установив значения x и y.   -  person derM    schedule 18.11.2017
comment
Ваши комментарии имеют смысл, и я изначально пытался использовать только прямоугольник. Однако, когда я это сделал, все мои предметы были сложены друг на друга. Добавление «height: myDelegate.height» к Rectangle правильно размещает делегаты, но затем Repeater (который сам является частью ColumnLayout) не получает правильную высоту, и элемент ниже Repeater размещается поверх Это. После долгих проб и ошибок я обнаружил, что Column или ColumnLayout решают мои проблемы. Однако мне было бы интересно узнать, почему Rectangle не работает должным образом.   -  person Knute Knudsen    schedule 19.11.2017
comment
Пожалуйста, добавьте небольшой рисунок, иллюстрирующий, чего именно вы пытаетесь достичь.   -  person derM    schedule 20.11.2017
comment
Я отредактировал вопрос, добавив немного графики, которая, я надеюсь, более четко объяснит мою проблему.   -  person Knute Knudsen    schedule 26.11.2017


Ответы (1)


Причина может показаться странной:

Семейство [...]Layout предназначено не только для упорядочивания объектов, но и для изменения их размера. Вы не должны устанавливать или изменять размеры в нем.

Чтобы выполнить свою работу, когда вы не используете доступные прикрепленные свойства для установки размеров, он будет использовать implicitWidth/Height ваших Items.

Если вы не установили неявные размеры, при добавлении новых элементов в макет их неявные размеры будут установлены равными их заданным размерам. Но это не привязка! Поэтому, если вы сейчас обновите height, implicitHeight останется в исходном размере, поэтому макет не будет реагировать на изменение.

Если вы добавите Column к своему делегату, все изменится: Column обновит свой implicitHeight в соответствии с ограничивающим прямоугольником своих дочерних элементов. Если вы теперь измените размер высоты Rectangles, Column адаптирует implicitHeight, а Layout отреагирует на изменение.

Теперь у вас есть следующие решения:

  1. Используйте присоединенное свойство Layout, чтобы установить и изменить подсказки размера.
  2. Используйте делегаты implicitHeight вместо height. Хотя это может быть семантически неправильно.
  3. Не используйте ColumnLayout, а просто обычный Column, когда вам не нужны дополнительные возможности компоновки (прикрепленные свойства и изменение размера элементов и т. д.), что, по-видимому, имеет место в вашей проблеме.

Column {
    anchors.centerIn: parent
    spacing: 5

    // Header goes here

    Repeater {
        model: 3
        delegate:
            Rectangle {
                width: 150
                height: width
                color: "#44ff0000"
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        console.log(parent.implicitHeight)
                        parent.height += 50
                    }
                }

        }
    }
    // Footer goes here

}
person derM    schedule 27.11.2017