我有一个带有属性的 Item
。此属性包含一个 JavaScript 对象数组,而这些对象又包含其他属性。
当我将对象的一个属性绑定(bind)到某个变量并且它的(变量)值更改触发绑定(bind)时,数组中的所有属性都将重置为它们的初始值。 我创建了一个小演示来展示这个问题。
C++代码:
// main.cpp
#include <QGuiApplication>
#include <QQuickWindow>
#include <QQmlApplicationEngine>
#include <QQmlContext>
class Test : public QObject
{
Q_OBJECT
Q_PROPERTY(QString value READ value NOTIFY valueChanged)
public:
Test(QObject* parent = 0) : QObject(parent) {}
QString value() const { return ""; }
Q_SIGNAL void valueChanged();
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Test test;
engine.rootContext()->setContextProperty("__test__", &test);
engine.load(QUrl(QStringLiteral("qrc:/ui/main.qml")));
return app.exec();
}
#include "main.moc"
QML代码:
// main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
id: container
visible: true
width: 640
height: 480
property int clicksCounter: 0
Item {
id: testObject
property var myArray : [{
name : "CustomName" + __test__.value,
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::valueChanged> 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__.valueChanged()
console.log("CLICK #" + container.clicksCounter + "[BLUE SQUARE] : [AFTER] testObject.myArray[0].name: " + testObject.myArray[0].name + ', testObject.myArray[0].boolFlag: ' + testObject.myArray[0].boolFlag)
}
}
}
}
这是我得到的:
qml: CLICK #1[RED SQUARE] : Set testObject.myArray[0] to TRUE qml: CLICK #1[RED SQUARE] : DONE
qml: CLICK #2[BLUE SQUARE] : Triggering notify by calling C++ <Test::valueChanged> 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: false
所以这里发生的是,在我将 testObject.myArray[0].boolFlag
从 false
设置为 true
并调用 test.valueChanged()
方法,我的标志自动重置为初始值。同样适用于任何其他使用的类型 - int
、string
等。
为什么会这样?
Visual Studio 已安装更新 4。
最佳答案
非常棘手,但这是 QML 的预期行为。您遇到的是绑定(bind)分配与程序分配的冲突,这是 QML 的常见缺陷。
首先,您已经设置了一个到 myArray
的绑定(bind)(实际上)表示任何时候 __test__.value
更改,重新分配一个文字数组给 我的数组
。稍后您通过程序修改该数组来破坏该绑定(bind)。请记住,文字数组实际上是 JavaScript 代码,每次在绑定(bind)中触发信号时都会对其求值。
因此,您在最后一个 console.log 中看到的不是 bool 已恢复,而是整个 myArray 已重置为新值,从绑定(bind)重建。
您真正想要的是一个新的 bool 属性,您可以将其分配给该属性,并且您的文字数组会绑定(bind)到该属性。像这样:
property bool myBoolFlag: false
property var myArray : [{
name : "CustomName" + __test__.value,
boolFlag : myBoolFlag
}]
然后,当您分配给 myBoolFlag
时,数组将被重建。当您触发 valueChanged
时,数组也会被重建,但这次 bool 值是从属性中提取的并具有正确的值。
关于qt - 在数组元素上使用绑定(bind)时出现奇怪的绑定(bind)行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31536574/