赞
踩
目录
在QML中,我们可以使用四种方式进行布局。最简单的就是设置元素的x和y属性,这就相当于在PyQt中使用控件的move()方法。其他三种分别是锚布局、布局定位器以及布局管理器。在本章,我们会详细了解这三种布局的使用方法。
所谓锚布局,就是设置好子元素的某个锚定线相对于其他元素某个锚定线的位置。每个元素都 有六条锚定线:top顶部线、bottom底部线、left左侧线、right右侧线、horizontalCenter水平居中线以及verticalCenter垂直居中线。如下图所示。
在QML代码中,我们通过设置元素的anchors属性来进行锚布局,请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
- color: "blue"
-
- Rectangle {
- id: childRect
- width: 100
- height: 100
- color: "red"
- anchors.left: root.left // 1
- anchors.verticalCenter: parent.verticalCenter // 2
- }
- }
运行结果:
代码解释:
这个示例中一共有两个矩形元素,蓝色的是父元素,红色的是子元素。
1. anchors.left属性表示子元素的左侧线,将该属性的值设置为root.left表示让子元素的左侧线与父元素的左侧线重合,那红色矩形自然就会包含在蓝色矩形的左侧了。
2. anchors.verticalCenter表示子元素的垂直居中线,将该属性的值设置为root.verticalCenter表示让子元素的垂直居中线与父元素的垂直居中线重合,那红色矩形就会在蓝色矩形垂直居中的位置上。
当然,各个元素在布局时,锚定线不一定是重合的,可能会有一些偏移。我们可以通过下面几个属性设置偏移量。
属性 | 解释 |
anchors.topMargin | 元素上边距,需要先设置好anchors.top属性的值 |
anchors.bottomMargin | 元素下边距,需要先设置好anchors.bottom属性的值 |
anchors.leftMargin | 元素左边距,需要先设置好anchors.left属性的值 |
anchors.rightMargin | 元素右边距,需要先设置好anchors.right属性的值 |
anchors.margins | 元素上下左右四个边距(同等距离),需要先设置好anchors.top,anchors.bottom, anchors.left和anchors.right属性的值。如果元素只元设置了anchors.top,那只有上边距起作用。 |
anchors.horizontalCenterOffset | 相对于水平居中线位置的偏移量,需要先设置好anchors.horizontalCenter属性的值 |
anchors.vrerticalCenterOffset | 相对于垂直居中线位置的偏移量,需要先设置好anchors.vrerticalCenter属性的值 |
现在我们将上方的代码修改下,给元素添加些偏移量。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
- color: "blue"
-
- Rectangle {
- id: childRect
- width: 100
- height: 100
- color: "red"
- anchors.left: root.left
- anchors.leftMargin: 20
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: 20
-
- }
- }
运行结果:
代码解释:
在设置好元素的左侧线和垂直居中线位置后,我们通过以下两行代码设置了红色矩形的左边距以及相对于垂直居中位置上的偏移量:
注:偏移量可以是浮点数。
锚布局还有两个方便的属性:anchors.centerIn和anchors.fill。前者可以将当前元素放在其他元素的正中位置,后者则可以让当前元素填充到其他元素中。请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
- color: "blue"
-
- Rectangle {
- id: childRect1
- width: 50
- height: 50
- color: "red"
- anchors.fill: root // 1
- }
-
- Rectangle {
- id: childRect2
- width: 50
- height: 50
- color: "green"
- anchors.centerIn: root // 2
- }
- }
运行结果:
代码解释:
1. childRect1矩形元素设置了anchors.fill属性,它会填充整个root矩形元素。其实就是让childRect1元素与root元素的顶部线、左侧线、底部以及右侧线重合,所以这行代码可以换成下面几行代码:
- anchors.top: root.top
- anchors.left: root.left
- anchors.bottom: root.bottom
- anchors.right: root.right
2. childRect2矩形元素设置了anchors.center属性,它会处在root矩形元素的正中位置。其实就是让childRect1元素与root元素的水平居中线以及垂直居中线重合,所以这行代码可以换成下面几行代码:
- anchors.horizontalCenter: root.horizontalCenter
- anchors.verticalCenter: root.verticalCenter
锚布局需要一个个地去设置元素的anchors属性,而布局定位器可以很方便地排列多个元素。QML提供了四种定位器:
每个定位器都有各自的特点,我们现在来一个个讲解下。
Row
行定位器Row用来水平排列各个元素,请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- Row {
- anchors.centerIn: root // 1
- spacing: 10 // 2
-
- Rectangle { // 3
- id: rect1
- width: 50
- height: 50
- color: "red"
- }
-
- Rectangle { // 3
- id: rect2
- width: 50
- height: 50
- color: "green"
- }
-
- Rectangle { // 3
- id: rect3
- width: 50
- height: 50
- color: "blue"
- }
- }
- }
运行结果:
代码解释:
1. 先用锚布局设置行定位器在窗口上的位置。
2. spacing属性用来设置各个子元素之间的水平空格距离。
3. 行定位器中有三个矩形子元素,颜色分别是红、绿、蓝。添加到行定位器中的子元素默认从左到右进行排列。我们可以设置layoutDirection属性让子元素从右到左进行排列,代码如下所示。
- Row {
- anchors.centerIn: root
- spacing: 10
- layoutDirection: Qt.RightToLeft // 默认是Qt.LeftToRight
- ...
- }
Column
列定位器Column用来垂直排列各个元素,请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- Column {
- anchors.centerIn: root // 1
- spacing: 10 // 2
-
- Rectangle { // 3
- id: rect1
- width: 50
- height: 50
- color: "red"
- }
-
- Rectangle { // 3
- id: rect2
- width: 50
- height: 50
- color: "green"
- }
-
- Rectangle { // 3
- id: rect3
- width: 50
- height: 50
- color: "blue"
- }
- }
- }
运行结果:
代码解释:
1. 先用锚布局设置列定位器在窗口上的位置。
2. spacing属性用来设置各个子元素之间的垂直空格距离。
3. 列定位器中有三个矩形子元素,颜色分别是红、绿、蓝。添加到列定位器中的子元素会从上到下进行排列。
Grid
网格定位器将各个子元素以网格形式排列,使用这个定位器时我们要定义网格的行列数。请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- Grid {
- anchors.centerIn: root // 1
- rows: 2 // 2
- columns: 2
- rowSpacing: 10 // 3
- columnSpacing: 10
-
- Rectangle { // 4
- id: rect1
- width: 50
- height: 50
- color: "red"
- }
-
- Rectangle { // 4
- id: rect2
- width: 50
- height: 50
- color: "green"
- }
-
- Rectangle { // 4
- id: rect3
- width: 50
- height: 50
- color: "blue"
- }
-
- Rectangle { // 4
- id: rect4
- width: 50
- height: 50
- color: "yellow"
- }
- }
- }
运行结果:
代码解释:
1. 先用锚布局设置网格定位器在窗口上的位置。
2. rows用来设置行数,coloumns用来设置列数。
3. rowSpacing属性用来设置各个子元素之间的水平空格距离,columnSpacing属性用来设置各个子元素之间的垂直空格距离。
4. 网格定位器中有四个矩形子元素,颜色分别是红、绿、蓝、黄。添加到网格定位器中的子元素默认会以从左到右,从上到下的顺序进行排列。一行放满之后,再放下一行。我们可以通过修改layoutDirection属性和flow属性来改变元素排列的顺序。
注:layoutDirection属性决定元素是先放左边还是先放右边,而flow属性决定元素是先填满行还是先填满列。
如果我们想让元素从右到左进行排列,可以把layoutDirection属性设置成Qt.RightToLeft,代码如下所示。
- Grid {
- anchors.centerIn: root
- rows: 2
- columns: 2
- rowSpacing: 10
- columnSpacing: 10
- layoutDirection: Qt.RightToLeft // 默认是Qt.LeftToRight
- ...
- }
如果我们想让元素先填满列,一列填满后再换另一列,可以把flow属性设置成Grid.TopToBottom,代码如下所示。
- Grid {
- anchors.centerIn: root
- rows: 2
- columns: 2
- rowSpacing: 10
- columnSpacing: 10
- flow: Grid.TopToBottom // 默认是Gird.LeftToRight
- ...
- }
Flow
流式定位器跟网格定位器很像,流式定位器不需要设置行列数,但需要设置宽高,如果某个元素放入这个定位器时,所有元素的总宽度或高度大于定位器的宽度或高度,那它就会将这个元素放在下一行或下一列。请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- Flow {
- anchors.centerIn: root // 1
- width: 150 // 2
- height: 50
-
- Rectangle { // 3
- id: rect1
- width: 50
- height: 50
- color: "red"
- }
-
- Rectangle { // 3
- id: rect2
- width: 50
- height: 50
- color: "green"
- }
-
- Rectangle { // 3
- id: rect3
- width: 80
- height: 50
- color: "blue"
- }
-
- Rectangle { // 3
- id: rect4
- width: 50
- height: 50
- color: "yellow"
- }
- }
- }
运行结果:
代码解释:
1. 先用锚布局设置流式定位器在窗口上的位置。
2. 设置流式定位器的宽高。
3. 流式定位器中有四个矩形子元素,颜色分别是红、绿、蓝、黄。蓝色矩形的宽度为80像素,其他矩形的宽度为50像素。因为流式定位器默认是先填满行,所以我们应该看矩形元素的总宽度是不是大于定位器的宽度。当红色和绿色矩形放入后,定位器第一行宽度还剩下150-100=50像素大小,但是蓝色矩形宽度为80像素,所以蓝色矩形只能放在下一行。
我们可以通过修改flow属性来让流式定位器先填满列,那这时候我们就要从高度这方面看是否要换列了。请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- Flow {
- anchors.centerIn: root
- width: 50
- height: 150
- flow: Grid.TopToBottom // 默认是Grid.LeftToRight
-
- Rectangle {
- id: rect1
- width: 50
- height: 50
- color: "red"
- }
-
- Rectangle {
- id: rect2
- width: 50
- height: 50
- color: "green"
- }
-
- Rectangle {
- id: rect3
- width: 50
- height: 80
- color: "blue"
- }
-
- Rectangle {
- id: rect4
- width: 50
- height: 50
- color: "yellow"
- }
- }
- }
运行结果:
我们还可以将layoutDirection属性设置为Qt.RightToLeft,让元素从右往左放置(默认是Qt.LeftToRight)。也可以设置spacing属性让各个元素之间出现间隔。注意设置spacing属性后,流式定位器会把间隔大小也算进去。比方说定位器高度是100,间隔设为10,矩形元素高度为50,那此时第一列只能够放入一个矩形,因为100 - 50 - 10 = 40,剩余40像素小于矩形高度,所以第二个矩形只能放在第二列。请看下方示例代码。
- import QtQuick 2.0
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- Flow {
- anchors.centerIn: root
- width: 50
- height: 100
- spacing: 10
- flow: Grid.TopToBottom
-
- Rectangle {
- id: rect1
- width: 50
- height: 50
- color: "red"
- }
-
- Rectangle {
- id: rect2
- width: 50
- height: 50
- color: "green"
- }
-
- Rectangle {
- id: rect3
- width: 50
- height: 50
- color: "blue"
- }
- }
- }
布局管理器包括以下三种:
管理器和定位器的用法类似,不过我们可以用管理器进行更细微的布局操作。使用布局管理器前,需要先导入Layouts模块。
import QtQuick.Layouts 1.1
RowLayout
RowLayout就是水平布局各个子元素,跟Row定位器类似,不过添加到RowLayout中的各个元素可以使用以下附加属性。
属性 | 解释 |
Layout.minimumWidth | 最小宽度 |
Layout.minimumHeight | 最小高度 |
Layout.preferredWidth | 期望宽度 |
Layout.preferredHeight | 期望高度 |
Layout.maximumWidth | 最大宽度 |
Layout.maximumHeight | 最大高度 |
Layout.fillWidth | 填满剩余的宽度 |
Layout.fillHeight | 填满剩余的高度 |
Layout.alignment | 对齐 |
Layout.margins | 上下左右边距 |
Layout.leftMargin | 左边距 |
Layout.rightMargin | 右边距 |
Layout.topMargin | 上边距 |
Layout.bottomMargin | 下边距 |
请看下方示例代码。
- import QtQuick 2.0
- import QtQuick.Layouts 1.1
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- RowLayout {
- anchors.centerIn: parent // 1
- width: root.width // 2
- height: root.height
-
- Rectangle {
- id: rect1
- width: 50
- height: 50
- color: "red"
- Layout.leftMargin: 20 // 3
- }
-
- Rectangle {
- id: rect2
- width: 50
- height: 50
- color: "green"
- Layout.fillHeight: true // 4
- }
-
- Rectangle {
- id: rect3
- width: 50
- height: 50
- color: "blue"
- Layout.fillWidth: true // 5
- }
- }
- }
运行结果:
代码解释:
1. 先用锚布局设置行布局管理器在窗口上的位置。
2. 设置行布局管理器的大小,在这个示例中我们让它等同于窗口大小。
3. 设置红色矩形元素的左边距为20,并设置它的对齐方式为顶部对齐。
4. 让绿色矩形元素填满管理器中剩余的高度空间,因为同列上没有其他元素,所以绿色矩形的高度就等于布局管理(或窗口)的高度了。
5. 让蓝色矩形元素填满管理器中剩余的宽度空间。
ColumnLayout
ColumnLayout就是垂直布局各个子元素,只是跟RowLayout管理器在布局方向上不同,附加属性是一样的,笔者这里就不再赘述。
GridLayout
GridLayout就是以网格的形式布局各个子元素,跟Grid定位器类似。GridLayout管理器赋予子元素的附加属性比RowLayout和ColumnLayout多了四个:
属性 | 解释 |
Layout.row | 元素所在的行索引(0表示第1行) |
Layout.column | 元素所在的列索引(0表示第1列) |
Layout.rowSpan | 元素占据的行数(默认是1) |
Layout.columnSpan | 元素占据的列数(默认是1) |
请看下方示例代码。
- import QtQuick 2.0
- import QtQuick.Layouts 1.1
-
- Rectangle {
- id: root
- width: 300
- height: 200
-
- GridLayout {
- anchors.centerIn: parent // 1
- rows: 2 // 2
- columns: 2
-
- Rectangle {
- id: rect1
- width: 50
- height: 50
- color: "red"
- Layout.rowSpan: 2 // 3
- }
-
- Rectangle {
- id: rect2
- width: 50
- height: 50
- color: "green"
- Layout.row: 1 // 4
- Layout.column: 1
- }
-
- Rectangle {
- id: rect3
- width: 50
- height: 50
- color: "blue"
- Layout.row: 0 // 4
- Layout.column: 1
- }
- }
- }
运行结果:
代码解释:
1. 先用锚布局设置网格布局管理器在窗口上的位置。
2. 设置王额布局管理器的行列数。
3. 设置红色矩形元素占两行。
4. 调换绿色和蓝色两个矩形的位置。现在蓝色矩形的在网格布局管理器中的坐标为(0, 1),绿色矩形为(1, 1)。
1. QML中的RowLayout、ColumnLayout和GridLayout相当于PyQt中的QHorizontalLayout、QVerticalLayout和QGridLayout。
2. 锚布局是最常见的,会和其他布局方式搭配使用。
3. 管理器和定位器用法是类似的,只不过多了一些附加属性。可以先看下定位器的用法,再去学习管理器。
3. 布局定位器或管理器相互之间是可以嵌套的,也就是说可以嵌套布局,代码如下所示。
// 布局定位器嵌套 Row { Column { } Column { } } // 布局管理器嵌套 RowLayout { ColumnLayout { } ColumnLayout { } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。