在 QML 中更新对 var 属性的绑定

Posted

技术标签:

【中文标题】在 QML 中更新对 var 属性的绑定【英文标题】:Update bindings to var properties in QML 【发布时间】:2015-06-17 12:16:05 【问题描述】:

如果您查看this page,它会注意到当对象更改时,与 var 属性的绑定不会自动更新:

Item 
    property var car: new Object(wheels: 4)

    Text 
        text: "The car has " + car.wheels + " wheels";
    

    Component.onCompleted: 
        car.wheels = 6;
    

这将显示“汽车有 4 个***”,因为 car.wheels = 6; 不会自动触发更新。

页面没有说明如何解决这个问题?如何手动触发更新(不替换整个 car 对象)。

编辑: 明确地说,我不想替换整个 car 对象,我确实想使用 property var(我的实际property 是一个 javascript 对象,不能存储在任何原生 QML 属性类型中)。

编辑 2:这是一个使用 QtObject 的示例,不起作用(它说“汽车有 0 个***。”:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2

ApplicationWindow 
    width: 640
    height: 480
    visible: true

    property var car: QtObject  property var wheels: [] 

    Item 

        Text 
            text: "The car has " + car.wheels.length + " wheels";
        

        Component.onCompleted: 
            car.wheels.push("Rear-left");
            car.wheels.push("Rear-right");
            car.wheels.push("Front-left");
            car.wheels.push("Front-right");
        
    

【问题讨论】:

阅读this后我认为这是不可能的。但是您可以做的一件事是在数据操作后仅重新分配数组而不是整个对象:car.wheels = car.wheels 在推送元素后。至少比替换整个对象要好。但这取决于您的数据的结构... 是的,或者我考虑添加一个虚拟属性,例如:property bool update,然后在我的表达式中“使用”它,例如 text: "Blah blah" + (update ? "" : "")。然后手动更新只需执行update = !update 或类似的操作。大规模的黑客攻击。 仅供参考,将car 分配回自身也适用于Component.onCompleted 块的末尾,如car = car; 【参考方案1】:

实际上,页面确实说明了如何解决这个问题:

如果 onCompleted 处理程序改为使用“car = new Object(wheels: 6)” 那么文本将被更新为“这辆车有 6 个***”,因为 汽车属性本身会发生变化,这会导致变化 发出通知。

虽然我认为这违背了您不替换整个 car 对象的要求。

话虽如此,(至少)还有一个选择——使用QtObject:

Item

    property var car: QtObject  property int wheels: 4 

    Text 
        text: "The car has " + car.wheels + " wheels";
    

    Component.onCompleted: 
        car.wheels = 6;  // This will update the text
    

编辑

在新示例中,如果您需要使用包含基本类型的 Javascript 数组,您列出的代码不会触发更新。但是,如果您能够使用包含 QML 类型的 list,则可以使用以下解决方法:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2

ApplicationWindow 
    id: window
    width: 640
    height: 480
    visible: true

    property var car: QtObject  property list<Item> wheels 

    Component
    
        id: wheelComponent
        QtObject
        
            property var wheelName;
        
    

    Text
    
        anchors.fill: parent
        text: "The car has " + car.wheels.length + " wheels";

        Component.onCompleted:
        
            var wheel = wheelComponent.createObject(window, "wheelName": "Rear-left" );
            car.wheels += wheel;
        
    

根据您的需要,这可能会过于繁琐。创建property bool update 并在更改数组时更改它的hack 方法可能更可取。

【讨论】:

是的,我不想替换整个 car 对象。而使用QtObject 只是解决了问题——您现在使用的是property int 而不是property var。我的实际对象是一个多维矩阵,所以我必须使用property var @Timmmm 即使wheelsproperty var,它也可以工作。但是,我需要查看您的多维矩阵的示例,以了解 QtObject 是否可以在这里工作。 如果wheels 是一个非对象 JS 值(即双精度或字符串),它似乎可以工作,但如果它更复杂,例如一个Array。我在我的问题中添加了一个数组示例。顺便说一句,为帮助干杯。 @Timmmm 我已经通过答案更新了,虽然它可能无法满足您的需求。 创建一个新对象很麻烦,但是您可以通过简单地分配car = car 来触发更新通知,这应该不会创建一个新对象。【参考方案2】:

通知和自动绑定重新评估仅支持 QML 属性,不支持 JS 对象成员。

对于 var 内部的 JS 对象,只有当实际对象与另一个对象发生变化时才会触发通知,而不是当对象内部发生变化时。

但是,您可以通过在内部对象更改后手动发出 carChanged() 来强制重新评估绑定。

【讨论】:

【参考方案3】:

我以这种方式解决了相同的问题:

Item 
    property var car: new Object(wheels: 4)

    Text 
        Connections 
            target: car
            onWheelsChanged: 
                text: "The car has " + car.wheels + " wheels";
               
        

        text: "The car has " + car.wheels + " wheels";
    

    Component.onCompleted: 
        car.wheels = 6;
    

【讨论】:

以上是关于在 QML 中更新对 var 属性的绑定的主要内容,如果未能解决你的问题,请参考以下文章

从高度动态的 C++ 数据模型更新 QML:计时器与属性绑定

从宿主语言更新 QML 属性需要啥?

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

从 C++ 更新 QML Window 属性标志

QML 对象不更新显示

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