如何制作跟踪/控制任何布尔属性的QML切换按钮

Jer*_*ner 1 binding qt qml qtquick2

我今天的QML/QtQuick练习是制作一个小ToggleButton小部件,我可以实例化它来监视指定的布尔QML属性的状态,并且当我点击ToggleButton时也切换该属性的状态.

到目前为止,我有我的ToggleButton组件:

// 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";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

....这是我的小测试工具,用于查看它是否按照我想要的方式工作:

// 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
   }
}
Run Code Online (Sandbox Code Playgroud)

你可以通过将代码保存到ToggleButton.qml和main.qml(分别)然后运行"qmlscene main.qml"来运行它.

请注意,如果单击蓝色或绿色矩形,它将按预期工作; Rectangle对象的布尔"lighten"属性打开和关闭,导致Rectangle改变颜色,相关的ToggleButton也会做出适当的反应(当"lighten"属性为true时自动变为红色,而当"lighten"变亮时为灰色"财产是假的".

到目前为止,这么好,但如果你再单击ToggleButton本身,绑定就会被破坏:也就是说,点击ToggleButton会导致ToggleButton按预期变成红色/灰色,但是矩形的颜色不适合,在这之后,单击矩形不再导致ToggleButton的状态发生变化.

我的问题是,正确执行此操作的诀窍是什么,以便我始终在ToggleButton与其正在跟踪的属性之间存在双向对应关系?(请注意,理想的解决方案是尽可能少地为main.qml添加代码,因为我希望将此功能封装在ToggleButton.qml中,以最大限度地减少暴露给我的其他QML应用程序的复杂程度)

Fel*_*lix 5

这不起作用的原因是您用固定值覆盖绑定.通过在您手动分配值,您onClicked可以用值覆盖绑定.

问题是:QML现在不支持双向绑定.但是,有一些技巧可以创建一个.见http://imaginativethinking.ca/bi-directional-data-binding-qt-quick/

注意:isActive为什么不使用按钮的选中状态,而不是使用这样的属性?(从文档中)这样即使单击按钮,绑定也不会中断:

// 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";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)