Qt Quick 布局概述

使用 Qt Quick 布局在用户界面中排列元素。Qt Quick 布局会调整其元素的大小,这使得它们非常适合可调整大小的用户界面。

主要功能

Qt Quick 布局的某些主要功能包括

此外,GridLayout 还添加了以下功能

入门

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

import QtQuick.Layouts

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

简单布局

使用布局的目的是在布局大小改变时重新排列其子元素。这意味着应用程序必须确保布局被调整大小。在下面的代码片段中,通过指定 anchors.fill: parentRowLayout 确保了这一点。然而,您也可以通过其他方式实现,例如指定 宽度高度 属性。在同一片段中,橙色矩形 的固定大小为 100 x 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 像素。间距以及任何子元素的 implicitWidth 都会影响到布局的 implicitWidth。如果您依赖于默认行为,这很重要,因为它可能会影响您的布局设计。例如,以下代码片段中的两个 ColumnLayout 都设置了 Layout.fillWidth: true。他们自然都会得到相同的宽度。然而,由于内部 RowLayout 之间的默认 5 像素间距,第一个 ColumnLayoutimplicitWidth 变得更大,留给第二个的余地更少。例如

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
            }
        }
    }
}

此代码片段将生成如下布局

"A QML layout with default spacing"

为确保这两个列的大小相等,您可以选择以下方法之一

  1. RowLayout 的间距设置为 0,或
  2. 在两个 ColumnLayout 上设置相等值的 preferredWidth

指定首选大小

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

候选属性描述
Layout.preferredWidthLayout.preferredHeight这些属性应由应用程序修改,如果默认的隐式大小无法提供最佳布局。
implicitWidthimplicitHeight这些属性应由每个项目提供,以给出有意义的理想大小。例如,显示 Text 类型内容所需的大小。隐式宽度或高度为 0 被解释为无效。

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

注意: 如果您没有指定首选宽度或隐式宽度,布局将查询 宽度 作为有效首选宽度的最终值。然而,您不应该将 宽度 作为有效首选宽度的来源,因为这可能会导致意外的行为。例如,更改 宽度高度 属性不会触发布局重排,或者布局在强制进行全面重建时可能会使用实际宽度和高度——而不是QML文件中指定的宽度和高度。

大小约束

由于项目可以由其布局调整大小,因此布局需要知道所有在 Layout.fillWidthLayout.fillHeight 设置为 true 的项目中 最小首选最大 大小。

如果没有将布局绑定到特定大小,首选宽度和高度就是项的实际宽度和高度。如果布局设置为特定大小,它将根据其项的首选大小的比率分配额外空间,同时考虑最小和最大大小。所有项都设置了 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
        }
    }
}

"RowLayout at its minimum"

将每个项的约束结合起来,为布局元素提供这些隐式约束

最小首选最大
隐式约束(宽度)156306∞(Number.POSITIVE_INFINITY
隐式约束(高度)150150150

因此,布局不能比 156 更窄,也不能比 150 更高或更短,否则会违反其子项的任何约束。

连接窗口和布局

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

RowLayout {
    id: layout
    anchors.fill: parent

您可以使用布局的大小约束来确保窗口的大小不能超过布局约束。您可以从布局中获取大小约束,并将这些约束设置在 窗口 元素的 minimumWidthminimumHeightmaximumWidthmaximumHeight 上。以下代码确保窗口的大小不能超过布局的约束

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

注意: 因为在这种情况下 layout.Layout.maximumWidth 是无限的,所以我们无法将其绑定到窗口的 maximumWidth 属性,因为那是整数数字。因此,最大宽度设置为固定的 1000

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

width: layout.implicitWidth
height: layout.implicitHeight

跨域和扩展项

网格布局中使用span使子项占据多个单元格。例如,您可能有一组跨越两行的六个单元格的网格布局。顶层包含项目item1、item2和item3的Item。底层包含设置columnSpan: 3alignment: Qt.AlignHCenterItem项4。这使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
       }
    }
}

行和列的大小由其内容隐式给出。例如,一个按钮可能会影响其所在列的宽度或其所在行的宽度。这意味着网格布局不具有均匀分布。因此,您不能使用span来拉伸布局。要操纵项或布局的拉伸,请使用stretchFactor和/或大小提示。

注意:设置隐式或首选大小时,不要将相应的属性绑定到布局本身的宽度或高度或其对计算其大小依赖的项的宽度或高度,因为这可能导致难以追踪的循环依赖。

© 2024 The Qt Company Ltd. 本文档中的文档贡献属于其各自的版权所有者。提供的文档根据GNU自由文档许可证1.3版的条款许可,由自由软件基金会发布。Qt及其相应标志是芬兰和/或世界其他国家的The Qt Company Ltd.的商标。所有其他商标均属于其各自所有者。