简体   繁体   中英

QML unexpected binding

Now, while porting my app to Qt 5.9 I've faced some strange behavior. The code describing the issue is below:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    visible: true
    width: 600
    height: 800
    title: qsTr("Test")

    Row {
        id: base
        property var arr: []
        property color currentColor: "red"
        anchors.centerIn: parent
        spacing: 5
        Repeater {
            model: 10
            delegate: Rectangle {
                width: 50
                height: 50
                border.width: 1
                border.color: "grey"
                color: base.arr[index] === undefined ? "white" : base.arr[index]
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        base.currentColor = Qt.rgba(Math.random(),Math.random(),Math.random(),1);
                        base.arr[index] = base.currentColor;
                        base.arr = base.arr; // trick to fire changing event
                        console.log(base.arr)
                    }
                }
            }
        }
    }
}

So there is array of rectangles and while pressing one of them I get random color and place it in the array base.arr at some index as item one. There is a property base.currentColor to keep the current color. But the problem is that if I assign new color to an item all previous items change color too.

I guess the problem is in line

base.arr[index] = base.currentColor;

It looks that this line creates some unexpected binding or reference or whatever I don't see. As I know the only way to create binding in Js is Qt.binding but here I don't use that.

The workaround to break this behavior is something like this:

base.arr[index] = Qt.rgba(base.currentColor.r, base.currentColor.g, base.currentColor.b, base.currentColor.a);

but it looks overhead and dirty solution.

I would be glad if someone can explain this strange behavior.

QML color is actually a color object .

In JavaScript objects are copied by reference, so a QML color variable actually behaves more like a pointer.

On this line:

base.arr[index] = base.currentColor;

the array element is set as a reference to the currentColor object.

When each array element is set, it gets set as a reference to the same currentColor object! Thus changing the currentColor changes every element in the array.

Instead of this:

property color currentColor: "red"

use this:

property string currentColor: "red"

strings in QML are always copied by value, so you will no longer have a problem.

Full code:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    visible: true
    width: 600
    height: 800
    title: qsTr("Test")

    Row {
        id: base
        property var arr: []
        property string currentColor: "red"
        anchors.centerIn: parent
        spacing: 5
        Repeater {
            model: 10
            delegate: Rectangle {
                width: 50
                height: 50
                border.width: 1
                border.color: "grey"
                color: base.arr[index] === undefined ? "white" : base.arr[index]
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        base.currentColor = Qt.rgba(Math.random(),Math.random(),Math.random(),1);
                        base.arr[index] = base.currentColor;
                        base.arr = base.arr; // trick to fire changing event
                        console.log(base.arr)
                    }
                }
            }
        }
    }
}

What I can't understand is - you said you are porting your app to Qt 5.9... If you are porting from a previous version of Qt, then I am surprised that the code did not behave the same way in the previous version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM