QGraphicsScene :: removeItem()与自定义项类后崩溃

时间:2016-07-19 12:37:46

标签: c++ qt5 qgraphicsitem qgraphicsscene

我使用自定义项类的实例填充QGraphicsScene(包含QGraphicsPathItem)。在运行时的某个时刻,我尝试通过调用:

从场景中删除一个项目(及其子项)
delete pItem;

这会自动调用QGraphicsScene::removeItem(),但在下一次重绘期间,它也会导致类QGraphicsSceneFindItemBspTreeVisitor崩溃。

4 个答案:

答案 0 :(得分:3)

TL; DR:解决方案是确保{<3}}在 之前被 调用 现场。

问题是在从场景中删除项目期间,场景内部索引未正确更新,导致下次尝试绘制场景时崩溃。

因为在我的情况下,我使用来自QGraphicsPathItem的自定义子类,我只是将调用QGraphicsItem::prepareGeometryChange()放入其析构函数中,因为我没有手动从场景中删除项目(通过{{1 }}),但我只是简单地调用QGraphicsScene::removeItem(),后者会在之后触发项目的析构函数以及delete pItem;

答案 1 :(得分:2)

我使用PySide2遇到了同样的问题。

禁用BSP索引(如here所述)确实对我有用,并且很可能是该问题的实际解决方案。但是是次优的,因为我正在处理的场景可以任意变大。我还尝试在删除项目之前致电prepareGeometryChange,尽管这似乎确实能工作一段时间,但几周后再次出现了该错误。

(到目前为止)对我有用的是在删除项目本身之前手动删除所有子项目... 为此,我要覆盖Python中的QGraphicsScene::removeItem方法:

class GraphicsScene(QtWidgets.QGraphicsScene):
    def removeItem(self, item: QtWidgets.QGraphicsItem) -> None:
        for child_item in item.childItems():
            super().removeItem(child_item)
        super().removeItem(item)

请注意,由于QGraphicsScene::removeItem不是虚拟方法,因此这在C ++中不太一样,因此您可能必须添加自己的方法removeItemSafely或其他任何方法。

免责声明:其他方法也对我有效……直到没有奏效为止。自引入此解决方法以来,我还没有在QGraphicsSceneFindItemBspTreeVisitor::visit中看到崩溃,但这并不意味着这实际上是解决方案。使用风险自负。

答案 2 :(得分:0)

我遇到了这个问题,修复它真的很痛苦。除了崩溃,我还在屏幕上出现“guost”项目。

我在自定义updateGeometry()方法中更改了boundingRect大小2x,该方法更新了项目的边界框和形状缓存。

我正在将边界矩形初始化为QRectf():

boundingBox = QRectF();

...然后进行一些处理(并借此机会对场景中不需要的对象进行一些清理)。

最后将boundingRect的值设置为新的大小:

boundingBox = polygon.boundingRect();

单独调用prepareGeometryChange()并没有解决问题,因为我将它的大小改为两次。

解决方案是删除第一个归因。

答案 3 :(得分:0)

今天这个问题似乎持续了很长时间,而且还存在一些未解决的错误。

但是似乎有一种解决方法,我发现它很有用,经过数小时的调试,阅读和调查,我在这里找到了它:

https://forum.qt.io/topic/71316/qgraphicsscenefinditembsptreevisitor-visit-crashes-due-to-an-obsolete-paintevent-after-qgraphicsscene-removeitem/17

此处有关Graphics Scene的其他提示和技巧: https://tech-artists.org/t/qt-properly-removing-qgraphicitems/3063/6