【问题标题】:QML unexpected bindingQML 意外绑定
【发布时间】:2017-10-08 01:14:52
【问题描述】:

现在,在将我的应用程序移植到 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);

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

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

【问题讨论】:

    标签: qt qml


    【解决方案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 移植,那么我很惊讶代码在以前版本中的行为方式不同。

    【讨论】:

    • 感谢@Mark Ch 的回复。你说的都是对的,但我担心另一个问题。我猜在这里分配对对象的引用而不是复制它的值不是预期的行为。根据您的建议,简单对象的行为会有所不同吗?其中一部分分配引用(如color)并部分复制其值(如string)?
    • 我认为你的担心是对的,这对我来说似乎是一个错误。 5.9 上的这种行为是否与以前的版本不同?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多