gpt4 book ai didi

python - PyQt 中的 QGraphicsItem 什么时候被销毁?

转载 作者:行者123 更新时间:2023-12-01 09:14:14 25 4
gpt4 key购买 nike

QGraphicsItem 状态似乎从 To be destroy by: C/C++ 变为 To be destroy by: Python,而不是已毁但仍可访问。这是预期的行为吗?如果是这样,有人可以解释一下吗?

创建部分

node = QGraphicsRectItem()
self.scene.addItem(node)

print("Deleted ? ", sip.isdeleted(node))
print("Owned by Python ? ", sip.ispyowned(node))
sip.dump(node)

输出

Deleted ?  False
Owned by Python ? False
<PyQt5.QtWidgets.QGraphicsRectItem object at 0x7fcdb82371f8>
Reference count: 3
Address of wrapped object: 0x214bf80
Created by: Python
To be destroyed by: C/C++
Parent wrapper: <PyQt5.QtWidgets.QGraphicsScene object at 0x7fcdb821ea68>
Next sibling wrapper: <__main__.Host object at 0x7fcdb8237dc8>
Previous sibling wrapper: NULL
First child wrapper: NULL

删除部分

self.scene.removeItem(node)

print("Deleted ? ", sip.isdeleted(node))
print("Owned by Python ? ", sip.ispyowned(node))
sip.dump(node)

输出

Deleted ?  False
Owned by Python ? True
<PyQt5.QtWidgets.QGraphicsRectItem object at 0x7fcdb82371f8>
Reference count: 2
Address of wrapped object: 0x214bf80
Created by: Python
To be destroyed by: Python
Parent wrapper: NULL
Next sibling wrapper: NULL
Previous sibling wrapper: NULL
First child wrapper: NULL

删除后可以看到它现在属于Python。而且它仍然存在。为什么?

最佳答案

当你 add the item to the scene, Qt takes ownership of it ,因此您不需要在 Python 端保留对它的显式引用。这意味着当场景被删除时,该项目的 C++ 部分也将被删除 - 如果没有其他对 Python 部分的引用,它也将被垃圾收集(因此不会留下任何东西)。

当你 remove the item from the scene, ownership passes back to the caller ,现在对删除它负有全部责任。如果QGraphicsRectItem继承了QObject,您可以调用deleteLater()来删除C++部分 - 但这仍然会给您留下空的Python包装器,所以实际上并没有多大区别。

删除 PyQt 包装器的方法与任何其他 Python 对象相同 - 即使用 del,或者简单地让它超出范围并允许它在正常情况下被垃圾收集方式。没有特殊的 PyQt 方法来删​​除此类对象,因为不需要任何特殊的方法。

在您的示例中,您实际上从未尝试删除该项目,因此 sip 报告的信息完全符合预期。

最后,请注意,始终可以独立于 PyQt 包装器删除 C++ 部分。如果您这样做,然后尝试访问该项目的方法,您将收到 RuntimeError:

>>> scene = QGraphicsScene()
>>> node = QGraphicsRectItem()
>>> scene.addItem(node)
>>> del scene
>>> node.rect()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: wrapped C/C++ object of type QGraphicsRectItem has been deleted

更新:

下面是一个演示,展示了当项目从场景中删除并允许超出范围时如何对其进行垃圾收集。当然,如果在其他地方有对该项目的任何引用(即,如果引用计数 > 1),则该项目将不会被删除。

import sip, gc
from PyQt5 import QtCore, QtWidgets

app = QtWidgets.QApplication(['test'])

scene = QtWidgets.QGraphicsScene()

def test():
node = QtWidgets.QGraphicsRectItem()
scene.addItem(node)
scene.removeItem(node)
print("Deleted ? ", sip.isdeleted(node))
print("Owned by Python ? ", sip.ispyowned(node))
sip.dump(node)
print()

test()

print('gc collect...')

gc.collect()

for obj in gc.get_objects():
if isinstance(obj, QtWidgets.QGraphicsRectItem):
print(obj)
break
else:
print('deleted')

输出:

Deleted ?  False
Owned by Python ? True
<PyQt5.QtWidgets.QGraphicsRectItem object at 0x7f90f66d5798>
Reference count: 3
Address of wrapped object: 0x205bd80
Created by: Python
To be destroyed by: Python
Parent wrapper: NULL
Next sibling wrapper: NULL
Previous sibling wrapper: NULL
First child wrapper: NULL

gc collect...
deleted

关于python - PyQt 中的 QGraphicsItem 什么时候被销毁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51392167/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com