QML学习笔记(二十五)QML的anchors(锚点)
前言
Anchors锚点是QML中用于将元素相对于其他元素进行定位的技术之一,这一概念在QWidget中是没有的,我们需要对它有更多了解和认识。
一、了解Anchors
我们先查阅帮助文档:
翻译一下:
用锚定位
除了更传统的网格、行和列之外,Qt Quick还提供了一种使用锚点概念布局项目的方法。每个项目都可以被认为有一组7条不可见的“锚线”:左、水平中心、右、上、垂直中心、基线和底部。
基线(上图未显示)对应于文本所在的假想线。对于没有文本的项目,它与顶部相同。
Qt快速锚定系统允许您定义不同项目锚线之间的关系。
用更简单的话来说,QML的锚定位机制为每一个组件赋予了七条锚线,分别是上下左右、水平中心、垂直中心,以及基线(文本相关),我们可以使用它们进行定位。
二、利用锚线进行九宫格定位
我希望设置九个小矩形,仅通过锚的锚线定位来进行九宫格形式的排布。让我们新建一个项目,开始尝试一下!
先做一个容器矩形,并画上线框。
Window {visible: truewidth: 640height: 480title: qsTr("Qml Anchors")Rectangle{id: containerRectIdwidth: 300height: widthborder.color: "black"anchors.centerIn: parent}
}
接下来,我们开始往上面添加矩形:
Rectangle{id: topLeftRectIdwidth: 100height: widthcolor: "magenta"Text {anchors.centerIn: parenttext: "1"font.pointSize: 20}}
这是左上角第一个矩形,可以看到组件没有设置锚点的话,默认就是父容器的左上角位置。
接下来添加第二个矩形,希望在第一个矩形的右边。
Rectangle{id: topCenterRectIdanchors.left: topLeftRectIdwidth: 100height: widthcolor: "yellowgreen"Text {anchors.centerIn: parenttext: "2"font.pointSize: 20}}
可以看到这里设置了锚点:anchors.left: topLeftRectId
,可结果并不如期望:
很明显,第二个矩形把第一个盖住了。同时也看到了打印报错:
意思是,无法将QQuickRectangle分配给QQuickAnchorLine。
原来我们写错了,锚线只能设置在锚线上,无法直接设在组件之上,不然虽然能运行,但设置会无效。
改成anchors.left: topLeftRectId.right
,效果符合预期:
接下来我们添加上上3、4、5的矩形:
Rectangle{id: topRightRectIdanchors.left: topCenterRectId.rightwidth: 100height: widthcolor: "dodgerblue"Text {anchors.centerIn: parenttext: "3"font.pointSize: 20}}Rectangle{id: centerLeftRectIdanchors.top: topLeftRectId.bottomwidth: 100height: widthcolor: "red"Text {anchors.centerIn: parenttext: "4"font.pointSize: 20}}Rectangle{id: centerCenterRectIdwidth: 100height: widthcolor: "green"anchors.left: topLeftRectId.rightanchors.top: topRightRectId.bottomText {anchors.centerIn: parenttext: "5"font.pointSize: 20}}
效果符合预期:
这里说一下第五个矩形的定位:
Rectangle{id: centerCenterRectIdanchors.left: topLeftRectId.rightanchors.top: topRightRectId.bottom// ...}
这里设置矩形5的左锚线对其矩形1的右侧,上锚线对其矩形3的下锚线,可以看到,使用锚定位的时候,可以使用不相邻组件的锚线,即便它们可能离得很远。
接下来我们将剩余的矩形补充,即可完成九宫格的布局。
三、使用中心线定位
除了以上相对位置的锚线定位外,我们还可以使用父容器中心线来进行定位:
我们以第五个矩形为例:
// 1
anchors.left: topLeftRectId.right
anchors.top: topRightRectId.bottom// 2
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter//3
anchors.centerIn: parent
这三种方式实际上是一样的,第一种是子组件间的相对位置;第二种则让它的水平、垂直中心线对其父容器的水平、垂直中心线;至于第三种,则是我们之前最常用到,也最简洁的方式,让该组件居中在父容器的位置。实际上,第三种是第二种的简写。
四、总结
本节介绍了使用锚定位和锚线来进行组件的定位,这种方式实际上有些繁琐,必须要单独设置每一个组件的定位逻辑。
事实上,上述例子中虽然实现了九宫格,但如果父容器的窗口大小产生变化,里面九个矩形的位置则可能根据事先设定好的规则产生偏移。这种情况下以第五个矩形为例,其根据左侧的矩形4来定位和直接定位了父容器的中心这两种定位策略所导致的结果是完全不一样的。
比如我简单修改了父容器的尺寸,从300改为400:
是不是感觉一切都乱套了?因此,我们更希望用一种更加简单和灵活,甚至可以利用自伸缩和自适应的布局方式。这些将在之后进行学习和应用。