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的方式來清空錨的值。

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