【发布时间】:2017-04-21 15:23:19
【问题描述】:
虽然我通过 PyQt 使用 Python 中的 Qt,但这个问题同样适用于纯 Qt,只是语法有点不同,问题是一样的:
当我们想要在场景中处理 QGraphicsItem 对象时,我们调用scene.removeItem(item)。当我们想要在场景中处理 QGraphicsObject 对象时,我们调用 scene.removeItem(item),因为它派生自 QGraphicsItem,但我们也调用 item.deleteLater(),因为它派生自 QObject,这是推荐的处理方式QObjects(以便正确处理进出该项目的未决信号)。
问题是,由于 deleteLater() 的功能,对象项中的插槽可能会在项目从场景中移除后被调用。这要求我们在 slot 中测试 self.scene() 是否为 None。但这很容易出错,因为很容易忘记这样做,如果调用 slot,忘记这一点会导致异常。
另一种方法是在从场景中移除项目之前不调用 deleteLater(),但这需要手动断开项目与其他对象的连接。这与测试 self.scene() 在插槽中为 None 具有类似的缺点,并且很容易忘记断开插槽。
减轻这种错误来源(如果没有隐藏的陷阱)的更好方法是在 item 是 QGraphicsObject 时不调用 scene.removeItem(item),而只需调用它的 deleteLater():它似乎 ,基于一些简单的测试,当项目最终被销毁时,场景会自动从列表中删除项目。但是,我找不到任何说明这一点的 Qt 文档,我可能只是很幸运;也许在更现实的情况下,我会遇到内存泄漏或崩溃。
所以我倾向于在 item 是 QGraphicsObject 时调用 deleteLater() 而不调用 removeItem(),你认为这样安全吗?
【问题讨论】:
-
QGraphicsItem的源代码算作文档吗?析构函数隐式删除该项目并执行其他清理工作的全部负载 - 因此它看起来设计得很好,可以通过删除来处理删除。 -
@ekhumoro 哈哈,当我看到已针对此问题发布了新评论时,我正要查找它。您可以使用源代码中的相关代码发布答案吗?