QML意外绑定

时间:2017-10-06 19:16:38

标签: qt qml

现在,在将我的应用程序移植到Qt 5.9时,我遇到了一些奇怪的行为。描述该问题的代码如下:

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)
                    }
                }
            }
        }
    }
}

所以有一些矩形数组,在按下其中一个时,我会得到随机颜色,并将其作为第一项放在某个索引的数组base.arr中。有一个属性base.currentColor来保持当前颜色。但问题是,如果我为一个项目分配新颜色,所有以前的项目也会改变颜色。

我猜问题就在于

base.arr[index] = base.currentColor;

看起来这行创建了一些意想不到的绑定或引用或者我看不到的任何内容。据我所知,在Js中创建绑定的唯一方法是Qt.binding,但在这里我不使用它。

打破这种行为的解决方法是这样的:

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

但它看起来是开销和肮脏的解决方案。

如果有人能解释这种奇怪的行为,我会很高兴。

1 个答案:

答案 0 :(得分:1)

QML color实际上是一种颜色object

在JavaScript中,对象是通过引用复制的,因此QML color变量实际上更像是指针。

在这一行:

base.arr[index] = base.currentColor;

将数组元素设置为currentColor对象的引用

设置每个数组元素后,它将被设置为对同一个currentColor对象的引用!因此,更改currentColor会更改数组中的每个元素。

而不是:

property color currentColor: "red"

使用它:

property string currentColor: "red"

QML中的字符串始终按值复制,因此您将不再有问题。

完整代码:

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)
                    }
                }
            }
        }
    }
}

我无法理解的是 - 你说你正在将你的应用程序移植到Qt 5.9 ...如果你从之前版本的Qt移植,那么我很惊讶代码在前一版本中的行为方式不同。