#(81):元素布局
上一章我们介绍了 QML 中用于定位的几种元素,被称为定位器。除了定位器,QML 还提供了另外一种用于布局的机制。我们将这种机制成为锚点(anchor)。锚点允许我们灵活地设置两个元素的相对位置。它使两个元素之间形成一种类似于锚的关系,也就是两个元素之间形成一个固定点。锚点的行为类似于一种链接,它要比单纯地计算坐标改变更强。由于锚点描述的是相对位置,所以在使用锚点时,我们必须指定两个元素,声明其中一个元素相对于另外一个元素。锚点是`Item`元素的基本属性之一,因而适用于所有 QML 可视元素。
一个元素有 6 个主要的锚点的定位线,如下图所示:
[![](https://box.kancloud.cn/2015-12-29_5682328407b64.png)](http://files.devbean.net/images/2014/02/qml-anchors.png)
这 6 个定位线分别是:`top`、`bottom`、`left`、`right`、`horizontalCenter`和`verticalCenter`。对于`Text`元素,还有一个`baseline`锚点。每一个锚点定位线都可以结合一个偏移的数值。其中,`top`、`bottom`、`left`和`right`称为外边框;`horizontalCenter`、`verticalCenter`和`baseline`称为偏移量。
下面,我们使用例子来说明这些锚点的使用。首先,我们需要重新定义一下上一章使用过的`BlueRectangle`组件:
~~~
import QtQuick 2.0
Rectangle {
width: 48
height: 48
color: "blue"
border.color: Qt.lighter(color)
MouseArea {
anchors.fill: parent
drag.target: parent
}
}
~~~
简单来说,我们在`BlueRectangle`最后增加了一个`MouseArea`组件。前面的章节中,我们简单使用了这个组件。顾名思义,这是一个用于处理鼠标事件的组件。之前我们使用了它处理鼠标点击事件。这里,我们使用了其拖动事件。`anchors.fill: parent`一行的含义马上就会解释;`drag.target: parent`则说明拖动目标是`parent`。我们的拖动对象是`MouseArea`的父组件,也就是`BlueRectangle`组件。
接下来看第一个例子:
[![](https://box.kancloud.cn/2015-12-29_5682328415ee6.png)](http://files.devbean.net/images/2014/02/qml-anchors-fill.png)
代码如下:
~~~
import QtQuick 2.0
Rectangle {
id: root
width: 220
height: 220
color: "black"
GreenRectangle {
x: 10
y: 10
width: 100
height: 100
BlueRectangle {
width: 12
anchors.fill: parent
anchors.margins: 8
}
}
}
~~~
在这个例子中,我们使用`anchors.fill`设置内部蓝色矩形的锚点为填充(fill),填充的目的对象是`parent`;填充边距是 8px。注意,尽管我们设置了蓝色矩形宽度为 12px,但是因为锚点的优先级要高于宽度属性设置,所以蓝色矩形的实际宽度是 100px – 8px – 8px = 84px。
第二个例子:
[![](https://box.kancloud.cn/2015-12-29_5682328425c1d.png)](http://files.devbean.net/images/2014/02/qml-anchors-left.png)
代码如下:
~~~
import QtQuick 2.0
Rectangle {
id: root
width: 220
height: 220
color: "black"
GreenRectangle {
x: 10
y: 10
width: 100
height: 100
BlueRectangle {
width: 48
y: 8
anchors.left: parent.left
anchors.leftMargin: 8
}
}
}
~~~
这次,我们使用`anchors.left`设置内部蓝色矩形的锚点为父组件的左边线(parent.left);左边距是 8px。另外,我们可以试着拖动蓝色矩形,看它的移动方式。在我们拖动时,蓝色矩形只能沿着距离父组件左边 8px 的位置上下移动,这是由于我们设置了锚点的缘故。正如我们前面提到过的,锚点要比单纯地计算坐标改变的效果更强,更优先。
第三个例子:
[![](https://box.kancloud.cn/2015-12-29_5682328433e3f.png)](http://files.devbean.net/images/2014/02/qml-anchors-left-right.png)
代码如下:
~~~
import QtQuick 2.0
Rectangle {
id: root
width: 220
height: 220
color: "black"
GreenRectangle {
x: 10
y: 10
width: 100
height: 100
BlueRectangle {
width: 48
anchors.left: parent.right
}
}
}
~~~
这里,我们修改代码为`anchors.left: parent.right`,也就是将组件锚点的左边线设置为父组件的右边线。效果即如上图所示。当我们拖动组件时,依然只能上下移动。
下一个例子:
[![](https://box.kancloud.cn/2015-12-29_5682328444705.png)](http://files.devbean.net/images/2014/02/qml-anchors-horizontalcenter.png)
代码如下:
~~~
import QtQuick 2.0
Rectangle {
id: root
width: 220
height: 220
color: "black"
GreenRectangle {
x: 10
y: 10
width: 100
height: 100
BlueRectangle {
id: blue1
width: 48; height: 24
y: 8
anchors.horizontalCenter: parent.horizontalCenter
}
BlueRectangle {
id: blue2
width: 72; height: 24
anchors.top: blue1.bottom
anchors.topMargin: 4
anchors.horizontalCenter: blue1.horizontalCenter
}
}
}
~~~
这算是一个稍微复杂的例子。这里有两个蓝色矩形:`blue1`和`blue2`。`blue1`的锚点水平中心线设置为父组件的水平中心;`blue2`的锚点上边线相对于`blue1`的底部,其中边距为 4px,另外,我们还增加了一个水平中线为`blue1`的水平中线。这样,`blue1`相对于父组件,`blue2`相对于`blue1`,这样便决定了三者之间的相对关系。当我们拖动蓝色矩形时可以发现,`blue1`和`blue2`的相对位置始终不变,因为我们已经明确指定了这种相对位置,而二者可以像一个整体似的同时上下移动(因为我们没有指定其中任何一个的上下边距与父组件的关系)。
另外一个例子:
[![](https://box.kancloud.cn/2015-12-29_5682328453a87.png)](http://files.devbean.net/images/2014/02/qml-anchors-centerin.png)
代码如下所示:
~~~
import QtQuick 2.0
Rectangle {
id: root
width: 220
height: 220
color: "black"
GreenRectangle {
x: 10
y: 10
width: 100
height: 100
BlueRectangle {
width: 48
anchors.centerIn: parent
}
}
}
~~~
与第一个例子类似,我们使用的是`anchors.centerIn: parent`将蓝色矩形的中心固定在父组件的中心。由于我们已经指明是中心,所以也不能拖动这个蓝色矩形。
最后一个例子:
[![](https://box.kancloud.cn/2015-12-29_5682328462d50.png)](http://files.devbean.net/images/2014/02/qml-anchors-hc-vc.png)
代码如下:
~~~
import QtQuick 2.0
Rectangle {
id: root
width: 220
height: 220
color: "black"
GreenRectangle {
x: 10
y: 10
width: 100
height: 100
BlueRectangle {
width: 48
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: -12
anchors.verticalCenter: parent.verticalCenter
}
}
}
~~~
上一个例子中,`anchors.centerIn: parent`可以看作等价于`anchors.horizontalCenter: parent.horizontalCenter`和`anchors.verticalCenter: parent.verticalCenter`。而这里,我们设置了`anchors.horizontalCenterOffset`为 -12,也就是向左偏移 12px。当然,我们也可以在`anchors.centerIn: parent`的基础上增加`anchors.horizontalCenterOffset`的值,二者是等价的。由于我们在这里指定的相对位置已经很明确,拖动也是无效的。
至此,我们简单介绍了 QML 中定位器和锚点的概念。看起来这些元素和机制都很简单,但是,通过有机地结合,足以灵活应对更复杂的场景。我们所要做的就是不断熟悉、深化对这些定位布局技术的理解。
- (1)序
- (2)Qt 简介
- (3)Hello, world!
- (4)信号槽
- (5)自定义信号槽
- (6)Qt 模块简介
- (7)MainWindow 简介
- (8)添加动作
- (9)资源文件
- (10)对象模型
- (11)布局管理器
- (12)菜单栏、工具栏和状态栏
- (13)对话框简介
- (14)对话框数据传递
- (15)标准对话框 QMessageBox
- (16)深入 Qt5 信号槽新语法
- (17)文件对话框
- (18)事件
- (19)事件的接受与忽略
- (21)事件过滤器
- (22)事件总结
- (23)自定义事件
- (24)Qt 绘制系统简介
- (25)画刷和画笔
- (26)反走样
- (27)渐变
- (28)坐标系统
- (29)绘制设备
- (30)Graphics View Framework
- (31)贪吃蛇游戏(1)
- (32)贪吃蛇游戏(2)
- (33)贪吃蛇游戏(3)
- (34)贪吃蛇游戏(4)
- (35)文件
- (36)二进制文件读写
- (37)文本文件读写
- (38)存储容器
- (39)遍历容器
- (40)隐式数据共享
- (41)model/view 架构
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)视图和委托
- (47)视图选择
- (48)QSortFilterProxyModel
- (49)自定义只读模型
- (50)自定义可编辑模型
- (51)布尔表达式树模型
- (52)使用拖放
- (53)自定义拖放数据
- (54)剪贴板
- (55)数据库操作
- (56)使用模型操作数据库
- (57)可视化显示数据库数据
- (58)编辑数据库外键
- (59)使用流处理 XML
- (60)使用 DOM 处理 XML
- (61)使用 SAX 处理 XML
- (62)保存 XML
- (63)使用 QJson 处理 JSON
- (64)使用 QJsonDocument 处理 JSON
- (65)访问网络(1)
- (66)访问网络(2)
- (67)访问网络(3)
- (68)访问网络(4)
- (69)进程
- (70)进程间通信
- (71)线程简介
- (72)线程和事件循环
- (73)Qt 线程相关类
- (74)线程和 QObject
- (75)线程总结
- (76)QML 和 QtQuick 2
- (77)QML 语法
- (78)QML 基本元素
- (79)QML 组件
- (80)定位器
- (81)元素布局
- (82)输入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)动态视图
- (86)视图代理
- (87)模型-视图高级技术
- (88)Canvas
- (89)Canvas(续)