QGraphicsItem何时在PyQt中被销毁?

时间:2018-07-18 01:13:31

标签: python pyqt pyqt5 destroy qgraphicsitem

似乎QGraphicsItem的状态从To be destroyed by: C/C++变为To be destroyed 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所有。它仍然存在。为什么?

2 个答案:

答案 0 :(得分:1)

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时,他现在完全负责删除它。如果GlideApp.with(mContext) .asDrawable() .load(list.getImageObjects().get(0).getUrl()) .transforms(new CenterCrop(), new RoundedCorners(20)) .transition(DrawableTransitionOptions.withCrossFade()) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) .into(imageView); 继承了npm install,则可以调用QGraphicsRectItem删除C ++部分-但这仍将为您提供空的Python包装器,因此并没有太大的区别。 / p>

删除PyQt包装器的方式与其他任何python对象相同-即使用QObject,或只是使其超出范围并以常规方式对其进行垃圾收集。没有特殊的PyQt删除此类对象的方法,因为不需要任何特殊的操作。

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

最后,请注意,始终可以独立于PyQt包装器删除C ++部分。如果执行此操作,然后尝试访问该项目的方法,则会得到一个deleteLater()

del

更新

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

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 :(得分:0)

删除后,不要让它超出范围。它已从所有Qt中删除,但Python仍然具有用于引用该项目的node变量。