天天看點

QML 靜态值與屬性綁定

簡述

可以為 QML 對象中的屬性配置設定兩種類型的值 - 靜态值和綁定表達式,後者也稱為屬性綁定。

  • 靜态值:一個不依賴于其他屬性的常數值。
  • 綁定表達式:一個用于描述屬性間依賴關系的 JavaScript 表達式。

屬性綁定是 QML 的一個核心特性,允許指定不同對象屬性之間的依賴關系。當屬性的依賴項(屬性綁定中的變量)的值發生改變時,屬性将根據指定的關系自動更新。

| 版權聲明:一去、二三裡,未經部落客允許不得轉載。

靜态值

所謂靜态值,就是一個不依賴于其他屬性的常數值。例如:​

​width : 100​

​,其中 100 就是一個靜态值。

下面的示例,将 Rectangle 的 width 和 height 均配置設定為靜态值。

QML 靜态值與屬性綁定
import QtQuick 2.3

Rectangle {
    // 初始化指派 - 靜态值
    width: 200
    height: 200

    Rectangle {
        // 初始化指派 - 靜态值
        width: 100
        height: 100
        color: "blue"      

既然藍色 Rectangle 的 width 和 height 都是靜态值,那麼當父 Rectangle 大小發生變化時,藍色 Rectangle 的大小必然不會改變。

屬性綁定

屬性綁定,簡單的了解就是一個綁定表達式,用于描述屬性之間的依賴關系。例如:​

​width : parent.width / 2​

​。

QML 引擎作為屬性綁定的幕後推手,在時刻監視屬性的依賴項,當檢測到任何依賴項的值發生改變後,就會自動重新計算綁定表達式,并為屬性配置設定新的結果。

使用屬性綁定

要建立一個屬性綁定,需要為屬性配置設定一個 JavaScript 表達式,該表達式将計算所需的值。最簡單的情況,綁定是對另一屬性的引用。

下面的示例,将藍色 Rectangle 的 width 綁定到其 parent 的 width:

QML 靜态值與屬性綁定
import QtQuick 2.3

Rectangle {
    width:200
    height: 200

    Rectangle {
        width: parent.width
        height: 100
        color: "blue"}
}      

每當父 Rectangle 的 width 發生變化,藍色 Rectangle 的 width 就會自動更新為相同的值。

綁定可以包含任何有效的 JavaScript 表達式或語句,因為 QML 使用了一個符合标準的 JavaScript 引擎。綁定可以通路對象屬性、調用方法、并使用内置的 JavaScript 對象(例如:Date、Math)。下面是上述示例的其他可能性綁定:

// 通路對象屬性
width: parent.width / 2

// 使用内置的 JavaScript 對象 Math
width: Math.min(parent.width, parent.height)

// 使用三目運算符
width: parent.width > 100 ? parent.width : parent.width /2

// if-else 代碼塊中的 return 關鍵字可有可無
width: {
    if (parent.width > 100)
        return parent.width
    else
        return parent.width / 2
}

// 調用方法      

在文法上,綁定允許具有任意複雜性(例如:涉及多行或指令循環)。但是,如果綁定過于複雜,可能會降低代碼性能、可讀性、和可維護性。比較好的方法是:重新設計具有複雜綁定的元件,或者至少将綁定轉換為單獨的函數。

從 JavaScript 建立屬性綁定

具有綁定的屬性将根據需要自動更新,但是,如果稍後從 JavaScript 語句為該屬性重新配置設定一個靜态值,則将會移除綁定。

例如,下面的藍色 Rectangle 最初確定其 width 總是其 parent 的 width 的 1/4。但是,當按下空格鍵時,parent.width / 2 将作為靜态值指派給 width。随後,即使其 parent 的 width 發生變化,其 width 也将保持不變,因為靜态值的配置設定移除了綁定。

QML 靜态值與屬性綁定
import QtQuick 2.3

Rectangle {
    width: 200
    height: 200

    Rectangle {
        id: rect
        width: parent.width / 4
        height: 50
        color: "blue"

        focus: true
        Keys.onSpacePressed: {
            width = parent.width / 2      

如果目的是為了給藍色 Rectangle 一個固定的 width 并停止自動更新,那麼這沒有任何問題。但是,如果是為了給 width 和其 parent 的 width 建立一個新的關系,那麼新的綁定表達式必須被包裹在 Qt.binding() 函數中:

QML 靜态值與屬性綁定
//...
Keys.onSpacePressed: {
    width = Qt.binding(function() { parent.width / 2 })
}
//...      

現在,按下空格鍵後,矩形的高度将繼續自動更新,始終為其 parent 的 width 的 1/2。

在屬性綁定中使用 this

當從 JavaScript 建立一個屬性綁定時,this 關鍵字可用于引用接收綁定的對象,這有助于解決屬性名稱産生的歧義。

例如,下面的 Component.onCompleted 處理程式在 Item 的範圍内定義。此範圍内,width 是指 Item 的 width,而不是 Rectangle 的 width。要将 Rectangle 的 height 綁定到其自身的 width,綁定表達式必須顯式地引用 this.width(或者 rect.width):

import QtQuick 2.3

Item {
    width: 200
    height: 200

    Rectangle {
        id: rect
        width: 100
        color: "blue"
    }

    Component.onCompleted: {
        rect.height = Qt.binding(function() return this.width * 2 })
        console.log("rect.height = " + rect.height) // 列印 200, 而非 400      

繼續閱讀