QML 条件绑定未按预期工作

Posted

技术标签:

【中文标题】QML 条件绑定未按预期工作【英文标题】:QML conditional Binding not working as expected 【发布时间】:2015-02-18 09:25:44 【问题描述】:

如果我有一个简单的Binding 形式的对象:

Rectangle 
    height: 400
    width: 500

    property var someObj: null

    Binding on color 
        when:  someObj
        value: someObj.color
    

那么我希望当someObj 不是null 时,someObjcolor 属性绑定到该对象的color 属性。我实际得到的是运行时错误消息:

TypeError: Cannot read property 'color' of null

这不起作用的任何原因?

执行几乎等效的 javascript 表达式:

color: 
    if ( someObj != null ) 
        return someObj.color;
     else 
        return "black";
    

按预期工作。

【问题讨论】:

在我看来是个错误。 嗯...您是否尝试减少到​​最小示例以隔离(可能的)错误?如果您可以发布该最小示例,那么查看它会很有趣。 @BaCaRoZzo 我在问题中编辑了一个最小示例。 @Mitch 已经有一个关于这个的错误报告,也很旧:bugreports.qt.io/browse/QTBUG-22005 这里只是一个简单的color: someObj? someObj.color: "black" 就足够了,顺便说一句(请注意,当您在项目的“内部”您想要哪些属性时,您不需要实例化Binding 对象绑定) 【参考方案1】:

正如in the comment by BaCaRoZzo 所述,问题中给出的最小示例不起作用,因为它给出了ReferenceError: someObj is not defined。然而,在为Rectangle 使用id 修复此问题后,尽管出现了 TypeError,该示例仍然有效

Rectangle 
    id: rect

    height: 400
    width: 500

    property var someObj: null

    Binding on color 
        when:  rect.someObj
        value: rect.someObj.color
    

当设置rect.someObj 并包含color 属性时,这会按预期正确设置颜色。

TypeError 的原因是表达式 rect.someObj.color 在创建 Binding 时已被计算(请参阅QTBUG-22005)。 因此,为了防止TypeError,可以简单地检查rect.someObj 是否设置在Bindingvalue 表达式中:

    Binding on color 
        when:  rect.someObj
        value: rect.someObj ? rect.someObj.color : undefined
    

【讨论】:

【参考方案2】:

我会这样做:

import QtQuick 2.0
import QtQuick.Controls 1.4

Rectangle 
    height: 400
    width: 500

    property var someObj

    color: someObj ? someObj.color : "black"

    Button 
        id: buttonTest
        text: "test"
        onClicked: parent.someObj = test
    
    Button 
        id: buttonTest2
        anchors.left: buttonTest.right
        text: "test2"
        onClicked: parent.someObj = test2
    

    QtObject 
        id: test
        property color color: "red"
    

    QtObject 
        id: test2
        property color color: "blue"
    

如果 someObj 未定义,则矩形的颜色为黑色,如果定义了 someObj,则选择 color 属性的值。

编辑:我看到晚了,这只是 mlvljr 在 cmets 中建议的,抱歉。

【讨论】:

【参考方案3】:

QML 语法定义属性值初始化赋值右侧的花括号表示绑定赋值。这在初始化 var 属性时可能会造成混淆,因为 JavaScript 中的空花括号可以表示表达式块或空对象声明。 如果您希望将 var 属性初始化为空对象值,则应将花括号括在括号中

例如:

Item 
    property var first:     // nothing = undefined
    property var second:  // empty expression block = undefined
    property var third:  () // empty object

在前面的示例中,第一个属性绑定到一个空表达式,其结果为undefined。第二个属性绑定到包含单个空表达式块("") 的表达式,该表达式同样具有undefined 结果。第三个属性绑定到一个表达式,该表达式被评估为一个空对象声明,因此该属性将使用该空对象值进行初始化。

同样,JavaScript 中的冒号既可以是对象属性赋值,也可以是代码标签。因此,使用对象声明初始化 var 属性也可能需要括号

Item 
    property var first:  example: 'true'     // example is interpreted as a label
    property var second: ( example: 'true' ) // example is interpreted as a property
    property var third:  'example': 'true'   // example is interpreted as a property
    Component.onCompleted: 
        console.log(first.example) // prints 'undefined', as "first" was assigned a string
        console.log(second.example) // prints 'true'
        console.log(third.example) // prints 'true'
    

所以代码应该如下:

Rectangle 
    height: 400
    width: 500

    property var someObj: (color: '')

    Binding on color 
        when: someObj.color
        value: someObj.color
    

【讨论】:

以上是关于QML 条件绑定未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

如何有条件地禁用 QML 绑定到 C++ 后端?

猫鼬发现或条件未按预期工作

std::find 条件语句未按预期工作

相同“if”条件下的两个“==”等式运算符未按预期工作

如何使 QML TextField 绑定在 Android 下工作?

NSpredicate 上的正则表达式未按预期工作