用于更新属性的 QML 条件逻辑

Posted

技术标签:

【中文标题】用于更新属性的 QML 条件逻辑【英文标题】:QML condition logic for updating a property 【发布时间】:2018-11-25 09:36:17 【问题描述】:

我正在寻找一种逻辑,以便根据一些不同的条件更改图像源属性。

我创建了一个小示例,其中包含三个条件和三个由这些条件构建的要求。

如果某个需求处于活动状态,我想在图像区域中查看它的图片。 如果一个需求不活跃,我不想在图像区域看到它的图像。 如果两个需求同时处于活动状态,则可以只查看其中一个。

我的代码有问题,因为如果一个需求处于非活动状态,而另一个需求同时处于活动状态,最后一个需求将控制内容。但我希望显示图像比不显示图像具有更高的优先级。

有没有常见的方法来解决这个问题?

我有以下代码:

main.qml:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow 
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    property bool condition1: false
    property bool condition2: false
    property bool condition3: false

    Image
        id: image
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        width: 120
        height: 120
        source: ""
    

    Row 
        anchors.top: image.bottom
        anchors.horizontalCenter: parent.horizontalCenter

        Button 
            id: button1
            text: "Condition1 = " + condition1
            onClicked: condition1 = !condition1
        
        Button 
            id: button2
            text: "Condition2 = " + condition2
            onClicked: condition2 = !condition2
        
        Button 
            id: button3
            text: "Condition3 = " + condition3
            onClicked: condition3 = !condition3
        
    

    StateObserver
        condition: condition1 && condition2 && condition3
        bitmap: "Images/1.png"
        target: image
    
    StateObserver
        condition: !condition1 && condition2 && condition3
        bitmap: "Images/2.png"
        target: image
    
    StateObserver
        condition: !condition1 && !condition2 && condition3
        bitmap: "Images/3.png"
        target: image
    

StateObserver.qml

import QtQuick 2.0

Item 

    property bool condition

    property string bitmap

    property var target

    onConditionChanged: 
        if (condition)
        target.source = bitmap
        
        else 
            target.source = ""
        

        console.log("Change bitmap: " + bitmap)
    

【问题讨论】:

【参考方案1】:

我不认为这是一个合理的方法,因为绑定表达式评估的顺序是未指定的。

我要做的是有一个点来评估所有可能的组合并使用其结果来装配其余属性。

通过您的StateObserver,您基本上是在引入不必要的复杂性。您也不必考虑所有可能的状态配置。

你可以简单地:

  Image 
    id: image
    //...
    source: 
      if (condition1 && condition2 && condition3) return "Images/1.png"
      else if (!condition1 && condition2 && condition3) return "Images/2.png"
      else if (!condition1 && !condition2 && condition3) return "Images/3.png"
      else return ""
     
  

这意味着更少的代码和更少的对象,这意味着更低的内存和 CPU 使用率。

但是,如果您坚持使用当前方法,则可以使用 Binding 元素,这些元素可以使用 when 属性自动打开或关闭。

最后,您也可以使用 QML 自己的 state machine,尽管对于这样一个琐碎的情况,这将是矫枉过正。

【讨论】:

感谢 dtech!实际上,一个需求(StateObserver-Object)会更复杂,我最多需要 50 个。我认为将所有内容直接放在 Image-source 属性中可能会变得不清楚。我认为绑定可能正是我所需要的。 不幸的是,绑定与我上面发布的方法有同样的问题。如果绑定不活动,图像将包含绑定的最后内容,但我想让图像源回到“”,以防绑定不活动。 那么你应该添加一个绑定 Binding on source value: ""; when: someBooleanExpressionThatIsTrueWhenNoOtherBindingIsActive - 类似于 dtech 绑定中的最后一行【参考方案2】:

根据 dtech 的评论,我创建了一个使用状态的示例。这像预期的那样工作,我能够将状态(要求)与 main.qml(布局)分开。谢谢!

main.qml:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow 
    id: mainApp
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    property bool condition1: false
    property bool condition2: false
    property bool condition3: false

    Image
        id: image

        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        width: 120
        height: 120

        Img_StateList
            container: image
        
    


    Row 
        anchors.top: image.bottom
        anchors.horizontalCenter: parent.horizontalCenter

        Button 
            id: button1
            text: "Condition1 = " + condition1
            onClicked: condition1 = !condition1
        
        Button 
            id: button2
            text: "Condition2 = " + condition2
            onClicked: condition2 = !condition2
        
        Button 
            id: button3
            text: "Condition3 = " + condition3
            onClicked: condition3 = !condition3
        
    

Img_StateList.qml:

import QtQuick 2.0

Item 
    property Image container;
    state: "default"
    states: [
        State 
            name: "default"
            PropertyChanges 
                target: container
                source: ''
            
        ,
        State 
            name: "Img1"
            when: condition1 && condition2 && condition3
            PropertyChanges 
                target: container
                source: 'Images/1.png'
            
        ,
        State 
            name: "Img2"
            when: !condition1 && condition2 && condition3
            PropertyChanges 
                target: container
                source: 'Images/2.png'
            
        ,
        State 
            name: "Img3"
            when: !condition1 && !condition2 && condition3
            PropertyChanges 
                target: container
                source: 'Images/3.png'
            
        
    ]

【讨论】:

以上是关于用于更新属性的 QML 条件逻辑的主要内容,如果未能解决你的问题,请参考以下文章

C# 转换字符串以用于逻辑条件

QML:有条件地设置属性组的不同属性

QML:有条件地设置属性组的不同属性

逻辑运算符

MailChimp:如何将条件逻辑与RSS源一起使用

帆软报表FineReport2016年1月份产品更新一览