当 Repeater 的委托高度改变时调整 ColumnLayout

Adjust ColumnLayout when a Repeater's delegate height changes

我创建了一个名为 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[=50的实例=] 在点击时相互重叠。但是,test2.qml 给出了所需的行为,并且 MyRectangle 的实例将它们的间距保持为 ColumnLayout 放大.

应derM的要求,我认为下面的GIF可能有助于更清楚地解释这一点。

test1.qml的(不希望的)行为:

test2.qml的(期望)行为:

为什么我必须将对象包装在 中才能获得所需的结果?

原因可能听起来很奇怪:

[...]Layout-family 不仅可以排列对象,还可以调整对象的大小。您不应该在其中设置或更改尺寸。

为了完成它的工作,当您不使用可用的附加属性来设置尺寸时,它将使用您的 ItemimplicitWidth/Height

如果您没有设置隐式尺寸,则在将新项目添加到布局时,它们的隐式尺寸将被设置为等于它们的设置尺寸。但这不是绑定!因此,如果您现在更新 heightimplicitHeight 将保持原始大小,因此布局不会对更改做出反应。

如果将 Column 添加到委托中,情况会发生变化:Column 根据其子项的边界矩形更新其 implicitHeight。如果您现在调整 Rectangles 的高度,Column 将适应 implicitHeightLayout 将对更改做出反应。

现在你有以下解决方案:

  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

}