python - QQmlPropertyMap 插入;神秘地插入无或删除其他值
问题描述
我在 PySide2 和 QML 中工作,而 QQmlPropertyList 正在做两件我觉得很奇怪的事情。
第一个是如果 QObject 是在同一语句中创建的,则将其分配为值不起作用:
from PySide2.QtCore import QObject
from PySide2.QtQml import QQmlPropertyMap
qmap = QQmlPropertyMap()
qmap.insert('test_key', QObject())
print(qmap.value('test_key'))
输出:
None
也许这与初始化 QObject 的时间有关?可以通过先将其分配给变量来修复它:
qmap = QQmlPropertyMap()
obj = QObject()
qmap.insert('test_key', obj)
print(qmap.value('test_key'))
<PySide2.QtCore.QObject(0x7fe8f26b5eb0) at 0x107075ec0>
但它变得陌生。忍受我。分配两个 QObjects 工作:
qmap = QQmlPropertyMap()
obj = QObject()
qmap.insert('test_key', obj)
obj2 = QObject()
qmap.insert('test_key2', obj2)
print(qmap.value('test_key'))
print(qmap.value('test_key2'))
<PySide2.QtCore.QObject(0x7f85f7f269e0) at 0x10d32b080>
<PySide2.QtCore.QObject(0x7f85f7f26b70) at 0x10d32b100>
我什至可以将同一个对象分配给多个键:
qmap = QQmlPropertyMap()
obj = QObject()
qmap.insert('test_key', obj)
qmap.insert('test_key2', obj)
print(qmap.value('test_key'))
print(qmap.value('test_key2'))
<PySide2.QtCore.QObject(0x7fde37d7d9d0) at 0x105cdc140>
<PySide2.QtCore.QObject(0x7fde37d7d9d0) at 0x105cdc140>
但是,如果我为两个不同的对象重用相同的变量名,第一个键的值会以某种方式被删除:
qmap = QQmlPropertyMap()
obj = QObject()
qmap.insert('test_key', obj)
obj = QObject()
qmap.insert('test_key2', obj)
print(qmap.value('test_key'))
print(qmap.value('test_key2'))
None
<PySide2.QtCore.QObject(0x7fcecaf072f0) at 0x111ba60c0>
怎么会这样?PySide 是否对运行时变量名称进行了某种隐藏的魔法?在这个例子中,这是微不足道的,但它在我的代码中导致了一个难以隔离的错误,我想更好地理解这一点。
解决方案
当您创建一个对象并为其分配相同的变量时,前一个对象被销毁,可以通过以下测试观察到:
class Foo:
def __del__(self):
print("destroyed")
print("before creating Foo object: 1")
foo = Foo()
print("after creating Foo object: 1")
print("before creating Foo object: 2")
foo = Foo()
print("after creating Foo object: 2")
输出
before creating Foo object: 1
after creating Foo object: 1
before creating Foo object: 2
destroyed
after creating Foo object: 2
destroyed
正如你所看到的,当第二个对象被分配给同一个变量时,第一个被销毁的被调用。所以这不是 PySide2 的魔力,而是 python 的魔力,同样可以用被破坏的信号来验证。
from PySide2.QtCore import QObject
print("before creating QObject object: 1")
qobject = QObject()
qobject.destroyed.connect(lambda _id=id(qobject): print("destroyed1: ", _id))
print("after creating QObject object: 1")
print("before creating QObject object: 2")
qobject = QObject()
qobject.destroyed.connect(lambda _id=id(qobject): print("destroyed2: ", _id))
print("after creating QObject object: 2")
输出:
before creating QObject object: 1
after creating QObject object: 1
before creating QObject object: 2
destroyed1: <PySide2.QtCore.QObject(0x562c1b6ee2f0) at 0x7f4a1faece40>
after creating QObject object: 2
如果你不希望这个问题发生,那么使用 Qt 的超能力,你可以将对象作为“qmap”的父级传递,因此所有权将由 QObject 持有,它将不再由 python 处理:
from PySide2.QtCore import QObject
from PySide2.QtQml import QQmlPropertyMap
qmap = QQmlPropertyMap()
obj = QObject(qmap)
qmap.insert("test_key", obj)
obj = QObject(qmap)
qmap.insert("test_key2", obj)
print(qmap.value("test_key"))
print(qmap.value("test_key2"))
输出:
<PySide2.QtCore.QObject(0x559629d1e230) at 0x7fef951f01c0>
<PySide2.QtCore.QObject(0x559629d1eae0) at 0x7fef951f0240>
更新:
为了更好地理解,我们必须知道 PySide2 的 QObject(也适用于 PyQt5)是 Qt 的 QObject 的一个包装器,也就是说,它类似于:
class PyQObject:
def __init__(self, *args):
self._qobject_cpp = CPPQObject(*args)
# ...
def __del__(self):
delete self._qobject_cpp
推荐阅读
- vb.net - 如何在 DatagridView Checkbox vb.net 中保持选中复选框
- rollup - 如何使用 Rollup 插件挂钩的返回承诺?
- api - 在 .net 核心 web api 中存储 JWT 令牌的位置?
- ios - React Native iOS 空白白屏和 EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- typescript - 在响应标头中设置 cookie,但未在浏览器中设置
- javascript - 使用json stringify html表单结果时的空数据
- chirp - 如何在 python 中以离线模式使用 Chirp.io
- python - 在python中的atom中添加模块
- python - Pandas pd.read_csv 不适用于简单的 sep=','
- sql - SQL中的多条Else语句逻辑