Qt Quick 元素布局

本文最后更新于:2021年2月7日 凌晨

Qt Quick 中有两套与元素布局相关的类库,一套叫作 Item Positioner (定位器),一套叫作 Item Layout (布局)。其实我们前面还讲了一个锚布局,它通过 Itemanchors 属性实现,是 Qt Quick 中非常灵活的一种布局方式。

定位器包括 Row(行定位器)、Column(列定位器)、Grid(表格定位器)、Flow(流式定位器)。

布局管理器包括行布局(RowLayout)、列布局(ColumnLayout)、表格布局(GridLayout)。

我们先讲定位器,然生再讲布局管理器。

定位器

定位器是一种容器元素,专门用来管理界面中的其他元素,与传统的 Qt Widgets 中的布局管理器类似。使用定位器,你可以很方便地把众多的元素组织在一起,形成非常规则的界面效果。不过有一点要注意的是,定位器不会改变它管理的元素的大小,即便用户调整了界面尺寸,它也坚持不干涉孩子匀的尺寸。这可能与你的期望不同,也与你使用 Qt Widgets 中的布局管理器的经验不同,不过如果你希望使用“自动根据界面尺寸变化调整孩子们的尺寸”这种竺性,可以使用 Qt Quick 中的布局管理器,它们的行为与你的经验和期望完全一致。

常用的定位器元素有下列几种:

  • Row
  • Column
  • Grid
  • Flow

Row

Row 沿着一行安置它的孩子们,在你需要水平放置一系列的 Item 时,它比锚布局更加方便。一旦你把一个 Item 交给 Row 来管理,那就不要在使用 Itemxyanchors等属性了,Row 会安排得妥妥的。

在一个 Row 内的 Item,可以使用 Positioner 附加属性来获知自己在 Row 中的详细位置信息。PositionerindexisFirstItemisLastItem 三个属性。

代码

main.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
width: 640
height: 480
visible: true
title: qsTr("Row 定位器")

Row {
id: colorRow
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
spacing: 4

Rectangle {
width: 60
height: 60
color: "red"
}

Rectangle {
width: 60
height: 60
color: "green"
}

Rectangle {
width: 60
height: 60
color: "blue"
}

Rectangle {
width: 60
height: 60
color: "yellow"
}

}

Button {
id: toggleDir
text: qsTr("切换方向")
font.bold: true
anchors.bottom: colorRow.top
anchors.bottomMargin: 4
anchors.left: parent.left
anchors.leftMargin: 4
onClicked: {
colorRow.layoutDirection = colorRow.layoutDirection ? Qt.LeftToRight : Qt.RightToLeft
}
}
}

演示

qml-row.gif

Row 有一个 spacing 属性,用来指定它管理的 Item 之间的间隔。还有一个 layoutDirection 属性,可以指定布局方向,取值为 Qt.LeftToRight 时从左到右放置 Item,这是默认行为,取值为 Qt.RightToLeft 时从右向左放置 Item

Row 还有 addmovepopulate 三个 Transition 类型的属性,分别指定应用于 Item 尜加、Item 移动、定位器初始化创建 Items 三种场景的过度动画,等我们学习了动画相关的内容之后再来实验这些属性。

Colomun

ColumnRow 类似,不过是在垂直方向上安排它的子 Item。在你需要垂直放置一系列的 Item 时,它比锚布局更加方便。

Column 本身也是一个 Item,可以使用 anchors 布局来决定它在父 Item 中的位置。Columnspacing 属性描述子 Item 之间的间隔。

代码

main.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
width: 640
height: 480
visible: true
title: qsTr("Column 定位器")

Column {
id: colorColumn
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
spacing: 6

Rectangle {
width: 60
height: 60
color: "red"
}

Rectangle {
width: 60
height: 60
color: "green"
}

Rectangle {
width: 60
height: 60
color: "blue"
}

Rectangle {
width: 60
height: 60
color: "yellow"
}
}
}

qml-column

Grid

Grid 在一个网格上安置它的子 Item,它会创建一个拥有很多单元格的网格,足够容纳它的所有子 ItemGrid 会从左到右、从上到下把它的子 Item 一个个塞到单元格里。Item 默认会被放在一个单元格左上角,即(0,0)位置。

你可以通过 rowscolumns 属性设定表格的行、列数。如果不设置,默认只有 4 列,而行数则会根据实际的 Item 数量自动计算。rowSpacingcolumnSpacing 指定行、列间距,单位是像素。

Gridflow 属性描述表格的流模式,Grid.LeftToRight 是默认值,这种流模式从左到右一个挨一个放置 Item,一行放满再放下一列。

horizontalItemAlignmentverticalItemAlignment 指定单元格对齐方式。默认的单元格对齐方式和 layoutDirection 以及 flow 有关。

代码

main.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
width: 640
height: 480
visible: true
title: qsTr("Grid 定位器")

Grid {
id: colorGrid
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
rows: 3
columns: 4
rowSpacing: 4
columnSpacing: 4

Rectangle {
width: 60
height: 60
color: "red"
}

Rectangle {
width: 60
height: 60
color: "green"
}

Rectangle {
width: 60
height: 60
color: "blue"
}

Rectangle {
width: 60
height: 60
color: "yellow"
}

Rectangle {
width: 60
height: 60
color: "pink"
}

Rectangle {
width: 60
height: 60
color: "gray"
}
}

Button {
id: flowBtn
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: colorGrid.top
anchors.bottomMargin: 4
text: "切换 Flow"
font.bold: true
onClicked: {
colorGrid.flow = colorGrid.flow ? Grid.LeftToRight : Grid.TopToBottom
}
}

Button {
anchors.left: flowBtn.right
anchors.leftMargin: 4
anchors.bottom: colorGrid.top
anchors.bottomMargin: 4
text: "切换 layoutDirection"
font.bold: true
onClicked: {
colorGrid.layoutDirection = colorGrid.layoutDirection ? Qt.LeftToRight : Qt.RightToLeft
}
}
}

演示

qml-grid.gif

Flow

Flow 其实和 Grid 类似,不同之处是它没有显式的行、列数,它会计算子 item 的尺寸,然后与自身尺寸比较,按需折行。Flowflow 属性,默认取值 Flow.LeftToRight,从左到右安排 Item,直到 Flow 本身的宽度不能容纳新的子 Item 时折行;当 flow 取值 Flow.TopToBottom时,从上到下安排 Item,直到 Flow 本身的高度不能容纳新的子 Item 时开始在下一列安排 Item

Flowspacing 属性描述 Item 之间的间隔。与 Row 等定位器元素一样,Flow 也有 addmovepopulate 三个与动画相关的属性。

代码

main.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
width: 640
height: 480
visible: true
title: qsTr("Flow 定位器")
Rectangle {
anchors.fill: parent

Flow {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
width: 200
height: 400
spacing: 4

Rectangle {
width: 60
height: 60
color: "red"
}
Rectangle {
width: 60
height: 60
color: "green"
}
Rectangle {
width: 60
height: 60
color: "blue"
}
Rectangle {
width: 60
height: 160
color: "yellow"
}
Rectangle {
width: 60
height: 60
color: "pink"
}
Rectangle {
width: 160
height: 60
color: "gray"
}
Rectangle {
width: 60
height: 96
color: "black"
}
}
}
}

qml-flow

布局管理器

Qt Quick 中的布局管理器与 Qt Widgets 中的相似,它与定位器的不同之处在于:布局管理器会自动调整子 Item 的尺寸来适应界面大小的变化。

要使用布局管理器,需要引入 Layouts 模块,这样:

1
import QtQuick.Layouts 1.1

GridLayout

GridLayoutQt C++ 中的 QGridLayout 功能类似,它在一个表格中安排它管理的 Item,如果用户调整界面尺寸,GridLayout 会自动重新调整 Item 的位置。

GridLayout 会根据 flow 属性来排列元素,这与 Grid 定位器类似,flow 属性的默认值是 GridLayout.LeftToRight,从左到右安排元素,一行结束再另起一行。而判定行结束的一条件是 columns 属性,它指定一个 GridLayout 的列数。如果 flow 取值 GridLayout.TopToBottomGridLaout 则从上到下安排元素,一列结束再另起一列。rows 属性指定 GridLayout 的行数,它阄决定何时新开一列来排布剩余的元素。

代码1

main.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12

Window {
width: 640
height: 480
visible: true
title: qsTr("GridLayout 布局管理器")

GridLayout {
id: colorGridLayout
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
rows: 3
columns: 3
rowSpacing: 4
columnSpacing: 4

Rectangle {
width: 60
height: 60
color: "red"
}
Rectangle {
width: 60
height: 60
color: "green"
}
Rectangle {
width: 60
height: 60
color: "blue"
}
Rectangle {
width: 60
height: 60
color: "yellow"
}
Rectangle {
width: 60
height: 60
color: "pink"
}
Rectangle {
width: 60
height: 60
color: "black"
}
Rectangle {
width: 60
height: 60
color: "gray"
}
}

Button {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: colorGridLayout.top
anchors.bottomMargin: 4
text: "切换 Flow"
font.bold: true
onClicked: {
colorGridLayout.flow = colorGridLayout.flow ? GridLayout.LeftToRight : GridLayout.TopToBottom
}
}
}

演示1

qml-grid-layout.gif

GridLayout 所管理的 Item,可以使用下列附加属性(这正是布局管理器和定位器之关键不同点):

  • Layout.row
  • Layout.column
  • Layout.rowSpan
  • Layout.columnSpan
  • Layout.minimumWidth
  • Layout.minimumHeight
  • Layout.preferredWidth
  • Layout.preferredHeight
  • Layout.maximumWidth
  • Layout.maximumHeight
  • Layout.fillWidth
  • Layout.fillHeight
  • Layout.alignment

RowLayout

RowLayout 管理的元素可以使用以下附加属性:

  • Layout.minimumWidth
  • Layout.minimumHeight
  • Layout.preferredWidth
  • Layout.preferredHeight
  • Layout.maximumWidth
  • Layout.maximumHeight
  • Layout.fillWidth
  • Layout.fillHeight
  • Layout.alignment

ColumnLayout

ColumnLayout 管理的元素可以使用以下附加属性:

  • Layout.minimumWidth
  • Layout.minimumHeight
  • Layout.preferredWidth
  • Layout.preferredHeight
  • Layout.maximumWidth
  • Layout.maximumHeight
  • Layout.fillWidth
  • Layout.fillHeight
  • Layout.alignment

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!