QML基础01【使用锚点定位】

本文源于官网文档,业余级翻译,仅供参考

使用锚点进行定位

基本概念

除了传统的网格,行,列之外,Qt Quick还提供了一种布局组件的方式,这种方式基于“锚”的概念。每个组件都可以被认为拥有一组不可见的“锚线”,一共7条(如下图):左,水平居中,右,顶部,竖直居中,基线,和底部
在这里插入图片描述
基线锚线没有在上图画出,它对应着文本所在的假想线。而对于没有文本的组件而言,基线锚线等同于顶部锚线
Qt Quick的锚定系统允许你在不同组件拥有的锚线之间定义关系,例如,你可以编写如下代码:

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

在这种情况下,rect2的左边沿被绑定到了rect1的右边沿,产生的效果如下图所示
在这里插入图片描述


你也可以指定多个锚点,例如

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

在这里插入图片描述


通过指定多个水平方向或者竖直方向上的锚点,你可以控制一个组件的尺寸,如下所示,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; ... }

在这里插入图片描述


还有一些提供便利性的锚点,例如anchors.fill可以方便地将组件的左,右,顶部,底部锚线设置为与目标组件的左,右,顶部,底部锚线一样。ahchors.centerIn是另一种便捷的锚点,它可以将组件的竖直居中,水平居中锚线设置为与目标组件的竖直居中,水平居中锚线一样

锚的外边距和偏移

锚定系统还允许为组件的锚设置外边距(margin)偏移量(offset)外边距(margin)指定了要保留在组件锚线外部的空白空间的总量,偏移量(offset)则允许基于中心锚线进行定位。一个组件可以通过leftMargin, rightMargin, topMagin, bottomMargin来分别指定其锚边距,或者,使用anchors.margin来为组件的全部四个边沿指定相同的外边距值。锚点的偏移则使horizontalCenterOffset, verticalCenterOffsetbaselineOffset 指定
在这里插入图片描述
下方的示例指定了一个左侧的外边距

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

在这种情况下,一个宽度为5像素的外边距会被保留在rect2的左侧,产生如下的效果
在这里插入图片描述
注意: 锚点的外边距仅对锚生效,他们不是用于设置组件外边距的通用手段。如果为一个组件的某个边沿设置了锚的外边距,而这个边沿却没有锚定到任何其他组件上,那么,此时这个外边距不会生效。


锚点变更

Qt Quick提供了AnchorChanges类型用于指定在某种状态中的锚

  State {
      name: "anchorRight"
      AnchorChanges {
          target: rect2
          anchors.right: parent.right
          anchors.left: undefined  //remove the left anchor
      }
  }

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

  Transition {
      AnchorAnimation {}  //animates any AnchorChanges in the corresponding state change
  }

锚也可以使用javascript进行强制修改,然而,应当谨慎下达这些修改指令,否则,它们会产生预料之外的结果,下方的示例阐述了这个问题:

  //bad code //存在问题的代码
  Rectangle {
      width: 50
      anchors.left: parent.left

      function reanchorToRight() {
          anchors.right = parent.right
          anchors.left = undefined
      }
  }

在这里插入图片描述


当上方示例中的函数reanchorToRight被调用后,该函数首先设置了右侧锚线,在这一刻,左侧和右侧的锚都被设置了,并且组件会被拉伸以填充它的父组件。当左侧锚被取消设置后,新的组件宽度会被保留。因此,当在javascript中更新锚时,你应该先取消任何不再使用的锚点,然后仅仅设置必要的锚,如下所示

  Rectangle {
      width: 50
      anchors.left: parent.left

      function reanchorToRight() {
          anchors.left = undefined
          anchors.right = parent.right
      }
  }

在这里插入图片描述
由于属性绑定的求值顺序是未定义的,因此,不推荐通过条件绑定来修改锚,因为这会导致上方案例中描述的顺序问题。在下方的错误示例代码中,矩形将会不断变宽,直到宽度和父组件一样,这是由于左侧和右侧的锚在属性绑定更新时被同时设置。

  //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或者,在锚定了左边沿与右边沿的情况下额外设置了一个宽度,都会导致不明确的结果,由于无法清晰明确地判断组件是否应当使用锚定位还是绝对定位。这对于在设置组件的y属性及高度的同时设定anchors.top和anchors.bottom是一样的。同样的情况也会在使用像Row, Col和Grid之类的定位工具时发生,因为这些工具会设置组件的x属性与y属性。如果你希望将基于锚定位变更到基于绝对定位,你可以通过设置锚为undefined的方式来清空锚的值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章