使用锚点定位

放置具有锚点属性的项目

除了更传统的GridRowColumn之外,Qt Quick 还提供了一种使用锚点概念来布局项目的方式。每个项目可以被认为具有一组7个不可见的“锚线”:lefthorizontalCenterrighttopverticalCenterbaselinebottom

../_images/edges_qml.png

基线(上图未显示)对应于文本所在的假想线。对于没有文本的项目,它与顶部相同。

Qt Quick 锚定系统允许您定义不同项目的锚线之间的关系。例如,您可以编写:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; ... }

在这种情况下,rect2 的左边缘被绑定到 rect1 的右边缘,产生以下结果:

../_images/edge1.png

您可以指定多个锚点。例如:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }
../_images/edge3.png

通过指定多个水平或垂直锚点,您可以控制项目的大小。下面,rect2被锚定在rect1的右侧和rect3的左侧。如果任何一个蓝色矩形被移动,rect2将根据需要拉伸和缩小:

Rectangle { id: rect1; x: 0; ... }
Rectangle { id: rect2; anchors.left: rect1.right; anchors.right: rect3.left; ... }
Rectangle { id: rect3; x: 150; ... }
../_images/edge4.png

还有一些方便的锚点。anchors.fill 是一个便利的锚点,等同于将左、右、上、下锚点设置为目标项目的左、右、上、下。anchors.centerIn 是另一个便利的锚点,等同于将垂直中心和水平中心锚点设置为目标项目的垂直中心和水平中心。

锚点边距和偏移量

锚定系统还允许为项目的锚点指定边距偏移量。边距指定在项目锚点外部留出的空白空间量,而偏移量允许使用中心锚线来操纵定位。项目可以通过leftMarginrightMargintopMarginbottomMargin单独指定其锚点边距,或使用anchors.margins为所有四个边缘指定相同的边距值。锚点偏移量使用horizontalCenterOffsetverticalCenterOffsetbaselineOffset来指定。

../_images/margins_qml.png

以下示例指定了左边距:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }

在这种情况下,rect2 的左侧保留了5像素的边距,产生以下结果:

../_images/edge2.png

注意

锚点边距仅适用于锚点;它们不是将边距应用于Item的通用方法。如果为边缘指定了锚点边距,但项目未锚定到该边缘的任何项目,则不应用该边距。

更改锚点

Qt Quick 提供了 AnchorChanges 类型,用于在状态中指定锚点。

AnchorChanges 可以使用 AnchorAnimation 类型进行动画处理。

锚点也可以在 JavaScript 中强制更改。然而,这些更改应谨慎排序,否则可能会产生意外的结果。以下示例说明了这个问题:

//错误的代码
Rectangle {
    width: 50
    anchors.left: parent.left

    function reanchorToRight() {
        anchors.right = parent.right
        anchors.left = undefined
    }
}
../_images/anchor_ordering_bad.png

当调用reanchorToRight时,函数首先设置右锚点。此时,左右锚点都已设置,项目将水平拉伸以填充其父容器。当左锚点取消设置时,新的宽度将保持不变。因此,在JavaScript中更新锚点时,您应该首先取消设置不再需要的任何锚点,然后才设置任何需要的新锚点,如下所示:

++—————————————–+ || .. 图片:: images/anchor_ordering.png| ++—————————————–+

由于绑定的评估顺序未定义,不建议通过条件绑定更改锚点,因为这可能导致上述顺序问题。在以下示例中,矩形最终将增长到其父级的全宽,因为在绑定更新期间将同时设置左锚点和右锚点。

//bad code
Rectangle {
    width: 50; height: 50
    anchors.left: state == "right" ? undefined : parent.left;
    anchors.right: state == "right" ? parent.right : undefined;
}

这应该重写为使用AnchorChanges,因为AnchorChanges会自动处理内部的排序问题。

限制

出于性能原因,您只能将项目锚定到其兄弟节点和直接父节点。例如,以下锚点是无效的,并且会产生警告:

//bad code
Item {
    id: group1
    Rectangle { id: rect1; ... }
}
Item {
    id: group2
    Rectangle { id: rect2; anchors.left: rect1.right; ... }    // invalid anchor!
}

此外,基于锚点的布局不能与绝对定位混合使用。如果一个项目指定了它的x位置并且还设置了anchors.left,或者锚定了它的左右边缘但另外设置了width,结果是未定义的,因为不清楚项目应该使用锚定还是绝对定位。同样的情况也适用于设置项目的yheightanchors.topanchors.bottom,或者设置anchors.fill以及widthheight。当使用如Row和Grid这样的定位器时,同样适用,这些定位器可能会设置项目的xy属性。如果你希望从使用基于锚点的布局改为绝对定位,你可以通过将其设置为undefined来清除锚点值。