首页 文章

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

提问于
浏览
1

我今天的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";
        }
    }
}

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

// 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时自动变为红色,而当“lighten”变亮时为灰色“ property 是假的” .

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

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

2 回答

  • 1

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

    问题是:QML现在不支持双向绑定 . 但是,有一些技巧可以创建一个 . 见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";
            }
        }
    }
    
  • 5

    看起来解决这个问题的一种方法是让ToggleButton使用别名属性而不是常规属性来声明其状态 . 这样只有一个外部属性(因为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
       }
    }
    

相关问题