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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何制作跟踪/控制任何布尔属性的QML切换按钮相关的知识,希望对你有一定的参考价值。

我今天的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”变亮时为灰色“财产是假的”。

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

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

答案

这不起作用的原因是您用固定值覆盖绑定。通过在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";
        }
    }
}
另一答案

看起来解决这个问题的一种方法是让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
   }
}

以上是关于如何制作跟踪/控制任何布尔属性的QML切换按钮的主要内容,如果未能解决你的问题,请参考以下文章

目标 C:按下按钮后切换属性的布尔值的问题

React JS - 切换布尔值

如何在QML(QT Creator)中使用发光脉动效果制作元素动画?

如何在 HTML5 中隐藏视频标签的全屏按钮

如何从另一个 QML 访问和控制 ListModel 的内容

如何在 QML 中设置 MessageDialog 的默认按钮?