Strange binding behavior when using binding on array's element
-
-
Okay, I managed to reproduce it. But for this I had to add C++ part.
C++ code is this:
// main.cpp #include <QGuiApplication> #include <QQuickWindow> #include <QQmlApplicationEngine> #include <QQmlContext> class Test : public QObject { Q_OBJECT Q_PROPERTY(QString emptyString READ getEmptyString NOTIFY valueChanged) QString getEmptyString(){ return ""; } public: Test(QObject* parent = 0) : QObject(parent) {} Q_INVOKABLE void triggerNotify() { valueChanged(); } signals: void valueChanged(); }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; Test* test = new Test(&engine); engine.rootContext()->setContextProperty("__test__", (QObject*)test); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, [](QObject* rootObject) { QQuickWindow *appWindow = qobject_cast<QQuickWindow *>(rootObject); appWindow->show(); }); engine.load(QUrl(QStringLiteral("qrc:/ui/main.qml"))); return app.exec(); }
QML code is this:
// main.qml import QtQuick 2.4 import QtQuick.Controls 1.3 ApplicationWindow { id: container width: 640 height: 480 property int clicksCounter: 0 Item { id: testObject property var myArray : [{ name : "CustomName" + __test__.emptyString, 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::triggerNotify> 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__.triggerNotify() console.log("CLICK #" + container.clicksCounter + "[BLUE SQUARE] : [AFTER] testObject.myArray[0].name: " + testObject.myArray[0].name + ', testObject.myArray[0].boolFlag: ' + testObject.myArray[0].boolFlag) } } } }
Here is what I get:
qml: CLICK #1[RED SQUARE] : Set testObject.myArray[0] to TRUE
qml: CLICK #1[RED SQUARE] : DONEqml: CLICK #2[BLUE SQUARE] : Triggering notify by calling C++ Test::triggerNotify method
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: falseSo what happens here is that after I set testObject.myArray[0].boolFlag from FALSE to TRUE and call test.triggerNotify() method my flag automatically resets to its initial value. Same goes if any other type used - int, string, etc. Why does this happen?
[UPDATE] QT 5.5 is used, Visual Studio 2013 Update 4 x32.
-
@geniuss Here is you answer:
http://doc.qt.io/qt-5/qml-var.html#change-notification-semantics
Edit: But that doesn't justify why it becomes false O_o -
@geniuss I would suggest you to ask at Qt Interest Mailing List. You can get an answer directly from Qt Engineers regarding these internals.