在数组元素上使用绑定时的奇怪绑定行为

时间:2015-07-21 10:30:01

标签: qt visual-studio-2013 qml qtquick2 qt5.5

我有Item有财产。此属性包含一个JavaScript对象数组,而这些对象又包含其他属性。

当我将某个对象属性的绑定设置为某个变量并且其(变量)值更改触发绑定时,数组中的所有属性都将重置为其初始值。 我已经创建了一个小型演示来展示问题。

C ++代码:

// main.cpp
#include <QGuiApplication>
#include <QQuickWindow>
#include <QQmlApplicationEngine>
#include <QQmlContext>

class Test : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString value READ value NOTIFY valueChanged)
public:
    Test(QObject* parent = 0) : QObject(parent) {}
    QString value() const { return ""; }
    Q_SIGNAL void valueChanged();   
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    Test test;
    engine.rootContext()->setContextProperty("__test__", &test);
    engine.load(QUrl(QStringLiteral("qrc:/ui/main.qml")));
    return app.exec();
}

#include "main.moc"

QML代码:

// main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3

ApplicationWindow {
    id: container
    visible: true

    width: 640
    height: 480

    property int clicksCounter: 0

    Item {
        id: testObject
        property var myArray : [{
            name : "CustomName" + __test__.value,
            boolFlag : false
        }]
    }

    Rectangle {
        x: 10
        y: 10

        width: 100
        height: 100
        color: "red"

        MouseArea {
            anchors.fill: parent
            onClicked: {
                container.clicksCounter++

                console.log("CLICK #" + container.clicksCounter + "[RED SQUARE] : Set testObject.myArray[0] to TRUE\n")
                testObject.myArray[0].boolFlag = true
                console.log("CLICK #" + container.clicksCounter + "[RED SQUARE] : DONE\n")
            }
        }
    }

    Rectangle {
        x: 120
        y: 10

        width: 100
        height: 100
        color: "blue"

        MouseArea {
            anchors.fill: parent
            onClicked: {
                container.clicksCounter++

                console.log("CLICK #" + container.clicksCounter + "[BLUE SQUARE] : Triggering notify by calling C++ <Test::valueChanged> method \n")
                console.log("CLICK #" + container.clicksCounter + "[BLUE SQUARE] : [BEFORE] testObject.myArray[0].name: " + testObject.myArray[0].name + ', testObject.myArray[0].boolFlag: ' + testObject.myArray[0].boolFlag)
                __test__.valueChanged()
                console.log("CLICK #" + container.clicksCounter + "[BLUE SQUARE] : [AFTER] testObject.myArray[0].name: " + testObject.myArray[0].name + ', testObject.myArray[0].boolFlag: ' + testObject.myArray[0].boolFlag)
            }
        }
    }
}

这是我得到的:

  

qml:CLICK#1 [RED SQUARE]:将testObject.myArray [0]设置为TRUE qml:   点击#1 [RED SQUARE]:完成

     

qml:CLICK#2 [BLUE SQUARE]:通过调用C ++触发通知   &lt;试验::的valueChanged&GT;方法

     

qml:CLICK#2 [BLUE SQUARE]:[BEFORE] testObject.myArray [0] .name:   CustomName,testObject.myArray [0] .boolFlag:true qml:CLICK#2 [BLUE   SQUARE]:[AFTER] testObject.myArray [0] .name:CustomName,   testObject.myArray [0] .boolFlag:false

所以这里发生的是,在我将testObject.myArray[0].boolFlagfalse设置为true并调用test.valueChanged()方法之后,我的标志会自动重置为其初始值。使用的任何其他类型也是如此 - intstring等。

为什么会这样?

Visual Studio安装了更新4。

1 个答案:

答案 0 :(得分:0)

非常棘手,但这是QML的预期行为。您所遭受的是绑定任务与程序分配之间的冲突,这是QML的常见缺陷。

首先,您已设置绑定到myArray(实际上)说任何时候__test__.value更改,重新将文字数组分配给myArray。然后通过程序修改该数组来破坏该绑定。请记住,文字数组实际上是每次信号在绑定中触发时都要评估的JavaScript代码。

所以,你在上一个console.log中看到的并不是bool已经被恢复,而是整个myArray被重置为一个新值,从绑定重建。

您真正想要的是可以分配给的新bool属性,并且您的文字数组将绑定到此属性。像这样:

property bool myBoolFlag: false
property var myArray : [{
        name : "CustomName" + __test__.value,
        boolFlag : myBoolFlag
    }]

然后,当您分配给myBoolFlag时,阵列会重建。当你解雇valueChanged时,数组也会被重建,但这次bool值是从属性中提取的,并且具有正确的值。