Qt QML中值的双重初始化
我有一个奇怪的问题,它埋在一个大项目的某个地方。到目前为止,我还无法在一个MCVE中复制它,但一旦成功,我将把它交上来 这是一个很简单的错误行为。基本上,我有一个带有属性的Qt QML中值的双重初始化,qt,qml,qtquick2,qt5.7,Qt,Qml,Qtquick2,Qt5.7,我有一个奇怪的问题,它埋在一个大项目的某个地方。到目前为止,我还无法在一个MCVE中复制它,但一旦成功,我将把它交上来 这是一个很简单的错误行为。基本上,我有一个带有属性的QtObject,我用初始值设置如下: TestObj.qml QtObject { id: root property int val1: { console.log('set val', root); return 42 } Component.onCompleted: console.log('C
QtObject
,我用初始值设置如下:
TestObj.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
!!!在这个例子中,我不会重现错误
我的项目的输出现在是:
set val TestObj\u QMLTYPE\u 44(0x33799fa8)
set val TestObj\u QMLTYPE\u 44(0x33799fa8)
构造对象TestObj\u QMLTYPE\u 44(0x33799fa8)
因此,尽管只创建一次对象,但初始属性分配会执行两次。由于我不知道在哪里寻找罪犯,我无法提供一个可复制的例子,但可能有人已经偶然发现了相同的情况并找到了解决方案 一个解决方案将是有益的,因为这个问题会导致一些对象的多个实例化,我无法销毁这些对象 也许他们能找到一种不需要黑客手段就能解决这个问题的方法 问题在于循环引用: 创建对象时,循环引用会导致奇怪的行为 TestObj1.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
TestObj2.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
结果:
qml:myVal
qml:set val TestObj_QMLTYPE_4(0x2c0bafb0)
qml:set val TestObj_QMLTYPE_4(0x2c0bafb0)
qml:构造对象
可能的原因是,{console.log('set val',root);return 42}
语句在allready分配给myVal
时未被处理,因此该语句被执行两次
虽然这在正常情况下没有问题,但只要这些属性中没有动态创建的对象,它可能会导致问题
TestObj3.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
TestObj4.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
结果:
qml:set obj
qml:PropertyObject创建的QObject(0x2c124708)
qml:set obj
qml:PropertyObject创建的QObject(0x2c1246f8)
qml:构造对象QObject(0x2c1246f8)
qml:QObject(0x2c1246f8)
所以你可以看到,这个对象确实被创建了两次
有一些变通办法:
属性别名obj:myObjectID
或属性QtObject obj:myObjectID
。这样做的缺点是,如果组件是可重用的,则用户无法替换该对象,或者该对象仍在创建中,从而浪费内存completed.onCompleted
中分配属性。这样做的缺点是,对象不可用、无法创建以及大量的无法读取属性。。。将出现0个空
错误。不过,他们希望不会破坏应用程序属性qtobj:(obj?obj:objPrototype.createObject(root))
。它会发出警告,但别这样。它只是一个绑定循环,将被检测并破坏QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
TestObj2.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
结果:
qml:myVal
qml:set val TestObj_QMLTYPE_4(0x2c0bafb0)
qml:set val TestObj_QMLTYPE_4(0x2c0bafb0)
qml:构造对象
可能的原因是,{console.log('set val',root);return 42}
语句在allready分配给myVal
时未被处理,因此该语句被执行两次
虽然这在正常情况下没有问题,但只要这些属性中没有动态创建的对象,它可能会导致问题
TestObj3.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
TestObj4.qml
QtObject {
id: root
property int val1: { console.log('set val', root); return 42 }
Component.onCompleted: console.log('Constructed Object', this)
}
import QtQuick 2.0
QtObject {
property Item paps
property int myVal: { console.log('myVal'); paps.val }
}
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
}
}
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)
}
}
}
import QtQuick 2.0
QtObject {
property Item paps
property QtObject myObj: paps.obj
Component.onCompleted: console.log(myObj)
}
结果:
qml:set obj
qml:PropertyObject创建的QObject(0x2c124708)
qml:set obj
qml:PropertyObject创建的QObject(0x2c1246f8)
qml:构造对象QObject(0x2c1246f8)
qml:QObject(0x2c1246f8)
所以你可以看到,这个对象确实被创建了两次
有一些变通办法:
属性别名obj:myObjectID
或属性QtObject obj:myObjectID
。这样做的缺点是,如果组件是可重用的,则用户无法替换该对象,或者该对象仍在创建中,从而浪费内存completed.onCompleted
中分配属性。这样做的缺点是,对象不可用、无法创建以及大量的无法读取属性。。。将出现0个空
错误。不过,他们希望不会破坏应用程序属性Qt