Python QGraphicsItem在PyQt中何时被销毁?
似乎Python QGraphicsItem在PyQt中何时被销毁?,python,pyqt,pyqt5,destroy,qgraphicsitem,Python,Pyqt,Pyqt5,Destroy,Qgraphicsitem,似乎QGraphicsItem的状态从由:C/C++销毁变为由:Python销毁,但未销毁且仍可访问。这是一种预期的行为吗?如果是,有人能解释一下吗 创作部分 输出 Deleted ? False Owned by Python ? False <PyQt5.QtWidgets.QGraphicsRectItem object at 0x7fcdb82371f8> Reference count: 3 Address of wrapped object: 0x21
QGraphicsItem
的状态从由:C/C++
销毁变为由:Python销毁,但未销毁且仍可访问。这是一种预期的行为吗?如果是,有人能解释一下吗
创作部分
输出
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
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
输出
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
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所有?真的
参考计数:2
包装对象的地址:0x214bf80
创建人:Python
被:Python破坏
父包装器:NULL
下一个同级包装器:NULL
上一个同级包装器:NULL
第一个子包装器:NULL
可以看出,删除后它现在归Python所有。它仍然存在。为什么?删除后,您不会让它超出范围。它已从Qt中删除,但Python仍然具有用于引用该项的节点变量 如果需要,则不需要在Python端保留对它的显式引用。这意味着,当场景被删除时,该项目的C++部分也将被删除,如果没有其他引用保存到Python部分,它也将被垃圾收集(因此将没有剩下任何东西)。
当你,谁现在有删除它的全部责任。如果<代码> qGraceCistalEng/<代码>继承<代码> QObjult<代码>,您可以调用<代码> DeleTelAtter()/Cuffe >删除C++部分——但这仍然会留给您空的Python包装器,所以它不会有太大的差别。
删除PyQt包装器的方法与删除任何其他python对象的方法相同,即使用del
,或者干脆让它超出范围,并允许以正常方式对其进行垃圾收集。没有特殊的PyQt方法来删除这些对象,因为不需要特殊的东西
在您的示例中,您实际上从未尝试删除该项,因此sip报告的信息完全符合预期
<>最后,注意,可以始终独立于PyQT包装器删除C++部分。如果执行此操作,然后尝试访问该项的方法,则会出现运行时错误
:
>>> 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
输出:
删除了吗?假的
Python所有?真的
参考计数:3
包装对象的地址:0x205bd80
创建人:Python
被:Python破坏
父包装器:NULL
下一个同级包装器:NULL
上一个同级包装器:NULL
第一个子包装器:NULL
gc收集。。。
删除
您是否希望使用removeItem()将该项从内存中删除?如果是这样,removeItem()不会从内存中删除该项,其目标是在另一个场景中重用该项,以便由程序员负责管理该内存,Qt中也会发生同样的情况。QListWidgetItem也有类似的行为。@eyllanesc同意。我不这么认为。重点是,使用<代码> PyQt < />代码,我没有明确的析构函数或<代码>删除< /C>指令,就像C++一样。那么我必须手动强制吗?如果是这样的话,除了使用sip或其他python解决方案(如del
),PyQt最好的方法是什么?QGraphicsRectItem
不会继承QObject
。谢谢。我的错。更新了。很奇怪,因为节点
(从QObject
继承,因此具有deleteLater
)已完全删除。即使python仍然有一个引用。deleteLater
背后的实现是什么?项目的所有权被传递给调用者(即,QGraphicscene在销毁项目时将不再删除项目)。
现在是有意义的,但不理解这种方式。而且,简单地让它超出范围,并允许以正常方式对其进行垃圾收集
从未看到节点被收集,即使在显式调用gc.collect()时也是如此。最后,您的建议是删除项目
,然后让它被收集?因为,正如我所说,它似乎不是collected@JustinIurman. 这一定是因为您保留了代码中其他地方的一些引用。我在我的答案中添加了一个演示,对我来说效果很好。谢谢,这就是问题所在。我在测试发生的函数中保存了一个本地引用。我的错。我现在得到了预期的行为。
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')