我有一个奇怪的问题,就是在一个大项目中的某个地方埋葬。到目前为止,我无法在 MCVE 中重现它,但只要我成功,我就会将其转入。
这是一个非常简单的行为。基本上我有QtObject
属性,我用这样的初始值设置:
TestObj.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
!!! 通过此示例,我不会重现错误 !!!
我的项目中的输出现在是:
set val TestObj_QMLTYPE_44(0x33799fa8)
set val TestObj_QMLTYPE_44(0x33799fa8)
Constructed Object TestObj_QMLTYPE_44(0x33799fa8)
因此,尽管该对象仅创建一次,但初始属性赋值执行两次 由于我不知道,在哪里寻找罪魁祸首,我无法生成一个可重复的例子,但也许有人在相同的情况下偶然发现并找到了解决方案。
解决方案将是有益的,因为这个问题导致一些对象的多个实例化,我无法破坏。
答案 0 :(得分:0)
Created Bug-Report: 也许他们找到了解决这个问题的方法,而不是黑客的解决方法
问题是循环引用:
循环引用在创建对象时会导致奇怪的行为。
<强> TestObj1.qml 强>
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
<强> TestObj2.qml 强>
import QtQuick 2.0
Item {
id: root
property int val: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object')
TestObj1 {
id: to1
paps: root
}
}
<强>结果:强>
qml: myVal
的qml: set val TestObj_QMLTYPE_4(0x2c0bafb0)
强>
的qml: set val TestObj_QMLTYPE_4(0x2c0bafb0)
强>
qml: Constructed Object
probalbe的原因是,语句{console.log('set val', root); return 42 }
尚未处理,当它已经全部分配给myVal
时,因此该语句执行了两次。
虽然这在普通情况下没有问题,但只要我们在这些属性中没有动态创建的对象,就可能会出现问题。
<强> TestObj3.qml 强>
import QtQuick 2.0
Item {
id: root
property QtObject obj: { console.log('set obj'); return objPrototype.createObject(root) }
Component.onCompleted: console.log('Constructed Object', obj)
TestObj4 {
id: to1
paps: root
}
Component {
id: objPrototype
QtObject {
id: op
Component.onCompleted: console.log('PropertyObject created', op)
}
}
}
<强> TestObj4.qml 强>
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
<强>结果:强>
qml: set obj
的qml: PropertyObject created QObject(0x2c124708)
强>
qml: set obj
的qml: PropertyObject created QObject(0x2c1246f8)
强>
qml: Constructed Object QObject(0x2c1246f8)
qml: QObject(0x2c1246f8)
所以你可以看到,对象确实创建了两次。
有一些解决方法:
property alias obj: myObjectID
或property QtObject obj: myObjectID
。这有缺点,如果组件可重用,用户无法替换该对象或仍然创建对象,浪费内存。Component.onCompleted
中分配属性。这有缺点,即对象不可用,uppon将出现创建和大量Can't read property ... of null
错误。他们希望不会破坏应用程序。property QtObject obj: (obj ? obj : objPrototype.createObject(root))
。它会发出警告,但来吧。它只是一个绑定循环,将被检测到并被破坏。这些解决方法没什么好看的,但可能是可用的东西。