Qt 快速布局:水平分布行项目?

问题描述 投票:0回答:2

我正在使用

ColumnLayout
与嵌套
RowLayout
s 的组合:

我正在尝试水平分布项目,以便每行第一个项目的左边缘对齐,每行最后一个项目的右边缘对齐,两者之间具有统一的间距。

作为附加约束,我希望窗口自动调整其大小以适应其内容,我相信我是通过从根向下传播

implicitWidth
/
implicitHeight
来实现的。

我使用

Rectangle
s 和
Repeater
s 来保持代码简短:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.12

Window {
    width: rootRect.implicitWidth
    height: rootRect.implicitHeight
    visible: true
    title: qsTr("Hello World")

    readonly property var items: [
        [[120, 80, 'red'], [100, 80, 'green'], [170, 40, 'blue']],
        [[60, 120, 'yellow'], [140, 80, 'orange'], [60, 100, 'cyan']],
        [[150, 100, 'purple'], [100, 80, 'blue'], [170, 40, 'orange']],
    ]

    Rectangle {
        id: rootRect
        // achieve a padding of 5
        implicitWidth: columnLayout.implicitWidth + 10
        implicitHeight: columnLayout.implicitHeight + 10

        ColumnLayout {
            id: columnLayout
            anchors.centerIn: parent // for above padding

            Repeater {
                model: items

                Item {
                    id: row
                    implicitWidth: rowLayout.implicitWidth //[*]
                    //[*] Layout.fillWidth: true
                    implicitHeight: rowLayout.implicitHeight
                    readonly property var rowItems: modelData

                    RowLayout {
                        id: rowLayout
                        //[*] Layout.fillWidth: true

                        Repeater {
                            model: rowItems

                            Rectangle {
                                width: modelData[0]
                                height: modelData[1]
                                color: modelData[2]
                            }
                        }
                    }
                }
            }
        }
    }
}

但是,无论我尝试什么(例如,使用

//[*] ...
添加/删除行的任何组合),我都无法让项目水平分布。

这看起来像是一个非常重要的操作,因为具有最大大小的行应该做它当前正在做的事情,而其他行应该简单地设置它们的大小,并相应地分配它们的项目……或者我可能忽略了一些属性Qt 快速布局。

注意:我使用的是布局而不是定位器,因为实际上我正在布置 Qt Quick Controls,它可以通过布局调整大小而受益。

编辑:当我将一个项目添加到样式行时,它再次中断:在线尝试

qt qml qtquick2 qt-quick
2个回答
2
投票

您需要在布局内的项目上设置

Layout.fillWidth
,否则布局将使用设置的宽度来布局项目。我在实际的
Item
周围使用了
Rectangle
来实现您想要的并能够在其上设置
Layout.fillWidth

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15

Window {
    id: root
    width: columnLayout.implicitWidth + 10
    height: columnLayout.implicitHeight + 10
    visible: true
    title: qsTr("Hello World")

    readonly property var items: [
        [[120, 80, 'red'], [100, 80, 'green'], [170, 40, 'blue']],
        [[60, 120, 'yellow'], [140, 80, 'orange'], [60, 100, 'cyan']],
        [[150, 100, 'purple'], [100, 80, 'blue'], [170, 40, 'orange']],
    ]

    ColumnLayout {
        id: columnLayout
        anchors.centerIn: parent

        Repeater {
            model: root.items

            RowLayout {
                Repeater {
                    id: nestedRepeater
                    model: modelData

                    Item {
                        Layout.fillWidth: true
                        Layout.minimumWidth: modelData[0]
                        Layout.minimumHeight: modelData[1]

                        Rectangle {
                            id: rect
                            property bool leftItem: index === 0
                            property bool rightItem: index === (nestedRepeater.count - 1)
                            property bool centerItem: !rect.leftItem && !rect.rightItem

                            anchors.centerIn: rect.centerItem ? parent : undefined
                            anchors.left: rect.leftItem ? parent.left : undefined
                            anchors.right: rect.rightItem ? parent.right : undefined

                            width: modelData[0]
                            height: modelData[1]
                            color: modelData[2]
                        }
                    }
                }
            }
        }
    }
}


此版本修复了我在下面的评论中提到的居中对齐问题。

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15

Window {
    id: root
    width: columnLayout.implicitWidth + 10
    height: columnLayout.implicitHeight + 10
    visible: true
    title: qsTr("Hello World")

    readonly property var items: [
        [[120, 80, 'red'], [100, 80, 'green'], [170, 40, 'blue']],
        [[60, 120, 'yellow'], [140, 80, 'orange'], [60, 100, 'cyan']],
        [[150, 100, 'purple'], [100, 80, 'blue'], [170, 40, 'orange']],
    ]

    ColumnLayout {
        id: columnLayout
        anchors.centerIn: parent

        Repeater {
            model: root.items

            RowLayout {
                Repeater {
                    id: nestedRepeater
                    model: modelData

                    Item {
                        id: item
                        property bool leftItem: index === 0
                        property bool rightItem: index === (nestedRepeater.count - 1)
                        property bool centerItem: !item.leftItem && !item.rightItem

                        Layout.fillWidth: item.centerItem
                        Layout.minimumWidth: modelData[0]
                        Layout.maximumWidth: (item.leftItem || item.rightItem) ? modelData[0] : -1
                        Layout.minimumHeight: modelData[1]

                        Rectangle {
                            anchors.centerIn: parent
                            width: modelData[0]
                            height: modelData[1]
                            color: modelData[2]
                        }
                    }
                }
            }
        }
    }
}


1
投票

这是另一个答案。 此解决方案基于您问题中的 QML 样式并进行了细微调整。

我使用了

Frame
组件。
Frame
,如果你以前没有用过它,它是一个非常方便的组件,可以用 padding 包装你的内容。所以,而不是
Rectangle
-
ColumnLayout
。这是
Frame
-
ColumnLayout
。这非常有用,因为它允许您删除
Rectangle
ColumnLayout
中不必要的像素数学。

我用

Item
来解决你的水平对齐问题。我通过设置
Item
Layout.preferredWidth
以及设置
Layout.fillWidth: true
来做到这一点。这两个属性一起使用时会导致
Item
变大并在水平方向均匀分布间距。

最后,我做了一些锚定,以确保

Rectangle
内的
Item
锚定在左、中或右。

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    background: Rectangle { color: "#444" }
    readonly property var items: [
        [[120, 80, 'red'], [100, 80, 'green'], [170, 40, 'blue']],
        [[60, 120, 'yellow'], [140, 80, 'orange'], [60, 100, 'cyan']],
        [[150, 100, 'purple'], [100, 80, 'blue'], [170, 40, 'orange']],
    ]
    Frame {
        background: Rectangle { }
        ColumnLayout {
            Repeater {
                model: items
                RowLayout {
                    id: rowLayout
                    Layout.fillWidth: true
                    Repeater {
                        model: modelData
                        Item {
                            Layout.preferredWidth: modelData[0]
                            Layout.preferredHeight: modelData[1]
                            Layout.fillWidth: true
                            Rectangle {
                                anchors.centerIn: index === 1 ? parent : undefined
                                anchors.right: index === 2 ? parent.right : undefined
                                width: modelData[0]
                                height: modelData[1]
                                color: modelData[2]
                            }
                        }
                    }
                }
            }
        }
    }
}

您可以在线试用!

© www.soinside.com 2019 - 2024. All rights reserved.