Qt Quick 布局概述#

一组用于在用户界面中排列 QML 元素的 API。

使用 Qt Quick 布局排列用户界面中的项。Qt Quick 布局可以调整它们的项目大小,这使得它们非常适合可调整大小的用户界面。

关键特性#

Qt Quick 布局的一些关键特性包括

此外,GridLayout 还添加了以下特性

入门指南#

要开始使用 Qt Quick 布局,请在您的 .qml 文件中使用以下导入语句将 QML 类型导入到应用程序中

下一步是创建一个简单布局。您也可以学习Qt Quick Layouts - 基本示例

简单布局#

使用布局的目的是在布局大小变化时重新排列其子项。这意味着应用程序必须确保布局被调整大小。在下面的代码片段中,通过指定anchors.fill: parentRowLayout确保了这一点。然而,您也可以通过其他方式达到这个目的,例如指定宽度高度属性。在同一个代码片段中,橙色矩形的大小是固定的,为100像素高和150像素宽,而梅色矩形将扩展以占用分配的全部空间。

Window {
    RowLayout {
        anchors.fill: parent
        spacing: 6
        Rectangle {
            color: 'azure'
            Layout.preferredWidth: 100
            Layout.preferredHeight: 150
        }
        Rectangle {
            color: "plum"
            Layout.fillWidth: true
            Layout.fillHeight: true
        }
    }
}

布局负责其子项的几何形状。这包括宽度高度xy锚点等属性。

重要:不要指定影响子项几何形状的属性。在子项上设置这些属性会引发利益冲突,结果不可预测。这也适用于子项是布局的情况。因此,只有没有父布局的布局才能有anchors.fill: parent

间距#

如前一个代码片段所示,RowLayout间距设置为6。这确保布局中的所有项目之间都有6像素的间距。

spacing: 6

如果您省略指定间距值,则布局将使用默认的5像素。间距以及任何子项的隐式宽度都贡献于布局的隐式宽度。如果您依赖于默认行为,请记住这一点,因为它可能会影响您的布局设计。例如,下面的两个** ColumnLayout **都设置为Layout.fillWidth: true。它们自然会认为它们会有相同的宽度。然而,由于内部RowLayout中各项目之间的默认5像素间距,第一个ColumnLayout隐式宽度会更大,留给第二个的空间更少。

ApplicationWindow {
    id: root
    width: 300
    height: 300
    visible: true

    RowLayout {
        anchors.fill: parent
        ColumnLayout {
            Rectangle {
                color: "tomato";
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
            RowLayout {
                Rectangle {
                    color: "navajowhite"
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                }
                Rectangle {
                    color: "darkseagreen"
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                }
            }
        }
        ColumnLayout {
            Rectangle {
                color: "lightpink"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
            Rectangle {
                color: "slategray"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
            Rectangle {
                color: "lightskyblue"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
        }
    }
}

此代码片段将产生以下布局:

../_images/layout-with-default-spacing.png

为了确保这两个列的大小相等,您可以

  1. RowLayout的间距设置为0,或者

  2. 将两个** ColumnLayout **的preferredWidth设置为相等的值。

指定首选大小#

对于每个项目,其有效首选大小可能来自多个候选属性之一。为了确定有效首选大小,项目按照以下顺序查询这些候选属性,并使用具有有效宽度或高度的第一个候选属性。

候选属性

描述

布局的 preferredWidth布局的 preferredHeight

如果默认的隐式大小不足以提供最佳排列,则应用程序应修改这些属性。

implicitWidthimplicitHeight

每个项目应提供这些属性以给出有意义的理想大小。例如,显示 Text 类型所需的大小。隐式宽度或高度设置为 0 被视为无效。

项目可以指定 Layout.preferredWidth 而无需指定 Layout.preferredHeight 。在这种情况下,实际的首选高度从 implicitHeight 中确定。

注意

如果您既没有指定 preferredWidth 也没有指定 implicitWidth,则布局会查询 width 作为最终的有效首选宽度值。然而,您不应依赖 width 作为有效首选宽度的来源,因为这可能会导致意外的行为。例如,更改 widthheight 属性不会触发布局重新排列,或者当被迫进行全面重建时,布局可能会使用实际宽度和高度而不是您在 QML 文件中指定的宽度和高度。

大小约束#

由于一个项目可以被其布局调整大小,布局需要知道所有 Layout.fillWidthLayout.fillHeight 设置为 true 的项目的 minimumpreferredmaximum 大小。

当布局绑定到特定大小自身时,首选宽度和高度是项目的实际宽度和高度。如果布局设置为特定大小,则它会根据其项目的首选大小的比例分配额外的空间,同时考虑最小和最大尺寸。首选和隐式大小作为比例和权重,当所有项目都设置 fillWidthfillHeight 时。

例如,以下会产生一个有两个矩形并排放置的布局,水平拉伸。橙色矩形 可以从 50x150 调整大小到 300x150,而 梅子矩形 可以从 100x100 调整大小到 ∞x100。只要每个项目的最小和最大宽度没有超过,梅子矩形的宽度将是橙色矩形的两倍。

RowLayout {
    id: layout
    anchors.fill: parent
    spacing: 6
    Rectangle {
        color: 'orange'
        Layout.fillWidth: true
        Layout.minimumWidth: 50
        Layout.preferredWidth: 100
        Layout.maximumWidth: 300
        Layout.minimumHeight: 150
        Text {
            anchors.centerIn: parent
            text: parent.width + 'x' + parent.height
        }
    }
    Rectangle {
        color: 'plum'
        Layout.fillWidth: true
        Layout.minimumWidth: 100
        Layout.preferredWidth: 200
        Layout.preferredHeight: 100
        Text {
            anchors.centerIn: parent
            text: parent.width + 'x' + parent.height
        }
    }
}
../_images/rowlayout-minimum.png

将每个项目的约束组合起来,给布局元素提供以下隐式约束

最小

首选

最大

隐式约束(宽度)

156

306

∞ (Number.POSITIVE_INFINITY)

隐式约束(高度)

150

150

150

因此,布局的宽度不能小于156,也不能比150更高或更低,否则会打破其子项的任何约束。

连接窗口和布局#

您可以使用正常的锚定概念来确保布局跟随窗口大小调整。

RowLayout {
    id: layout
    anchors.fill: parent

您可以使用布局的大小约束来确保窗口大小调整不会超过布局约束。您可以从布局中获取大小约束并设置到《Window》元素的《minimumWidth》、《minimumHeight》、《maximumWidth》和《maximumHeight》属性上。以下代码确保窗口大小调整不会超过布局的约束

minimumWidth: layout.Layout.minimumWidth
minimumHeight: layout.Layout.minimumHeight
maximumWidth: 1000
maximumHeight: layout.Layout.maximumHeight

注意

由于本例中《layout.Layout.maximumWidth》是无限的,我们无法将其绑定到《Window》的《maximumWidth》属性上,因为这是一个整数。因此,最大宽度被设置为固定值《1000》。

最后,将窗口的初始大小设置为布局的隐式大小

width: layout.implicitWidth
height: layout.implicitHeight

跨越和拉伸项#

在《GridLayout》中使用《spans》(跨越),让子项占据多个单元格。例如,您可能有一个跨越两个行的六列《GridLayout》。顶层包含item1、item2和item3。底层包含item4,指定《columnSpan: 3》和《alignment: Qt.AlignHCenter》。这样item4就在组成底层的三格中间。下面的代码片段是一个例子

ApplicationWindow {
    id: root
    width: 300
    height: 300
    visible: true

    GridLayout {
       rows: 2
       columns: 3
       Rectangle {
           color: 'cyan'
           implicitWidth: 50
           implicitHeight: 50
       }
       Rectangle {
           color: 'magenta'
           implicitWidth: 50
           implicitHeight: 50
       }
       Rectangle {
           color: 'yellow'
           implicitWidth: 50
           implicitHeight: 50
       }
       Rectangle {
           color: 'black'
           implicitWidth: 50
           implicitHeight: 50
           Layout.columnSpan: 3
           Layout.alignment: Qt.AlignHCenter
       }
    }
}

行和列的大小隐式地由其内容给定。例如,按钮可能会影响它所在的列的宽度,或者它所在的行的长度。这意味着《GridLayout》不具有均匀分布。因此,您不能使用跨度来拉伸布局。要操作项或布局的拉伸,请使用《stretchFactor》和/或大小提示。

注意

设置隐式大小或首选大小时,不要将相应的属性绑定到调整布局自身或其计算大小的依赖项的宽度和高度上,因为这可能引起难以追踪的循环依赖。