Reputation: 12864
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.
Upvotes: 2
Views: 88
Reputation: 3030
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.
Upvotes: 1