2016-07-08 82 views
1

我今天的QML/QtQuick練習是製作一個小的ToggleButton小部件,我可以實例化它來監視指定的布爾QML屬性的狀態,並切換該屬性的狀態,當我點擊ToggleButton。如何製作跟蹤/控制任何布爾屬性的QML切換按鈕

到目前爲止,我有這對我的切換按鈕組件:

// Contents of ToggleButton.qml 
import QtQuick 2.2 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.4 

Button { 
    property bool isActive: false 

    onClicked: { 
     isActive = !isActive; 
    } 

    style: ButtonStyle { 
     background: Rectangle { 
      border.width: control.activeFocus ? 2 : 1 
      border.color: "black" 
      radius: 4 
      color: isActive ? "red" : "gray"; 
     } 
    } 
} 

....這裏是我的小測試工具,我用它來看看它是否工作我想它,或者沒有辦法的辦法:

// Contents of main.qml 
import QtQuick 2.6 
import QtQuick.Window 2.2 

Window { 
    visible: true 
    width: 360 
    height: 360 

    Rectangle { 
     property bool lighten: false; 

     id:blueRect 
     x: 32; y:32; width:64; height:64 
     color: lighten ? "lightBlue" : "blue"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    Rectangle { 
     property bool lighten: false; 

     id:greenRect 
     x:192; y:32; width:64; height:64 
     color: lighten ? "lightGreen" : "green"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    ToggleButton { 
     x:32; y:128 
     text: "Bright Blue Rect" 
     isActive: blueRect.lighten 
    } 

    ToggleButton { 
     x:192; y:128 
     text: "Bright Green Rect" 
     isActive: greenRect.lighten 
    } 
} 

可以通過保存代碼ToggleButton.qml和main.qml(分別),然後運行「qmlscene main.qml」運行此。

請注意,如果您單擊藍色或綠色的矩形,它會按預期工作; Rectangle對象的布爾型「lighten」屬性被打開和關閉,導致Rectangle改變顏色,並且相關聯的ToggleButton也會作出適當的反應(當「lighten」屬性爲true時將其自身變成紅色,而在「變亮」時變爲灰色「財產是虛假的)。

到目前爲止,太棒了,但如果你再點擊ToggleButton本身,綁定就會被破壞:也就是說,單擊ToggleButton會導致ToggleButton按預期變成紅色/灰色,但矩形的顏色不會隨之而來,在完成之後,單擊矩形不再導致ToggleButton的狀態發生變化。

我的問題是,這樣做的好處是什麼,所以我總是有一個ToggleButton和它正在跟蹤的屬性之間的雙向對應關係? (請注意,理想的解決方案將盡可能少的代碼添加到main.qml中,因爲我希望將此功能封裝在ToggleButton.qml中,以最大限度地減少暴露給我的QML應用程序其餘部分的複雜度)

回答

1

看起來解決這個問題的一個方法是讓切換按鈕使用別名屬性聲明其狀態,而不是一個普通的財產。這樣只有一個外部屬性(因爲ToggleButton的內部屬性實際上只是外部屬性的別名),因此不需要雙向綁定。下面是預期的QML代碼,工程的更新版本:

ToggleButton.qml:

// Contents of ToggleButton.qml 
import QtQuick 2.2 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.4 

Button { 
    onClicked: { 
     isActive = !isActive; 
    } 

    style: ButtonStyle { 
     background: Rectangle { 
      border.width: control.activeFocus ? 2 : 1 
      border.color: "black" 
      radius: 4 
      color: isActive ? "red" : "gray"; 
     } 
    }  
} 

main.qml:

// Contents of main.qml 
import QtQuick 2.6 
import QtQuick.Window 2.2 

Window { 
    visible: true 
    width: 360 
    height: 360 

    Rectangle { 
     property bool lighten: false; 

     id:blueRect 
     x: 32; y:32; width:64; height:64 
     color: lighten ? "lightBlue" : "blue"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    Rectangle { 
     property bool lighten: false; 

     id:greenRect 
     x:192; y:32; width:64; height:64 
     color: lighten ? "lightGreen" : "green"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    ToggleButton { 
     x:32; y:128 
     text: "Bright Blue Rect" 
     property alias isActive: blueRect.lighten 
    } 

    ToggleButton { 
     x:192; y:128 
     text: "Bright Green Rect" 
     property alias isActive: greenRect.lighten 
    } 
} 
+0

有趣的使用屬性別名的!我之前沒有見過像這樣使用過的。到目前爲止,我只看到它們用於將組件的內部屬性暴露給它的API表面。雖然有一個設計問題:你的ToggleButton現在依賴於它的使用範圍。如果您忘記組件使用中的屬性別名,QML將嘗試在任何父級作用域中找到它。這可能會導致相當驚人的錯誤。組件的用戶也沒有提示他必須自己添加Active活動別名屬性,而不是像他期望的那樣設置一個值。 –

5

這不起作用的原因是您正在使用固定值覆蓋綁定。通過手動分配值onClicked您可以使用值覆蓋綁定。

問題是:QML現在不支持2way綁定。但是,有一些技巧可以創建一個。請參閱http://imaginativethinking.ca/bi-directional-data-binding-qt-quick/

注意:不要使用像這樣的isActive屬性,爲什麼不使用按鈕的選中狀態? (從documentation)這樣的結合不會打破,即使你按一下按鈕:

// Contents of ToggleButton.qml 
import QtQuick 2.2 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.4 

Button { 
    //use the "checked" property instead of your own "isActive" 

    checkable: true 

    style: ButtonStyle { 
     background: Rectangle { 
      border.width: control.activeFocus ? 2 : 1 
      border.color: "black" 
      radius: 4 
      color: checked? "red" : "gray"; 
     } 
    } 
}