Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python QGraphicsItem在PyQt中何时被销毁?_Python_Pyqt_Pyqt5_Destroy_Qgraphicsitem - Fatal编程技术网

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')