微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PyQT5 程序中的垃圾收集机制和正常情况有什么区别? 如果这是一个 GC 相关的问题

如何解决PyQT5 程序中的垃圾收集机制和正常情况有什么区别? 如果这是一个 GC 相关的问题

为了了解PyQT5中元类QObject对象删除特性,我编写了以下代码

from PyQt5.Qt import *


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setup_UI()
        self.setup_subUI()
        self.hook = None

    def setup_UI(self):
        self.setwindowTitle('MyWindowTitle')
        self.resize(600,400)

    def setup_subUI(self):
        obj1 = QObject()
        obj2 = QObject(obj1)
        obj3 = QObject(obj2)
        self.hook = obj1  # This is line 19.
        obj1.setobjectName('obj1')
        obj2.setobjectName('obj2')
        obj3.setobjectName('obj3')
        obj1.destroyed.connect(lambda obj: print(f'Object {obj.objectName()} has been released'))
        obj2.destroyed.connect(lambda obj: print(f'Object {obj.objectName()} has been released'))
        obj3.destroyed.connect(lambda obj: print(f'Object {obj.objectName()} has been released'))


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

上面的代码有几个明显的事实:

  1. Window 类有一个非必要属性 hook,最初用于绑定到 obj1
  2. obj1obj2 的父对象,obj2obj3 的父对象。如果引用计数中不涉及任何对象,则所有三个对象都将被快速恢复以激活下面的 destroyed 信号接收器并进一步打印此消息。

为了避免 GC,我添加了第 19 行以尝试保留它们,self.hook = obj1,但适得其反。

谜底如下:

如果将第 19 行更改为 self.other_attribute_not_schedule = obj1,程序将不会在 Window UI 实体关闭之前释放这 3 个对象。 更清楚的是,能否请您告诉我有关使用上述代码删除对象的更多详细信息,以及为什么当我使用另一行时它们没有删除

解决方法

当一个对象的引用数达到 0 时,垃圾收集会激活。在这种情况下,如果 Qt 允许,python 会尝试删除它。

在您的原始代码中,您首先调用 setup_subUI,这会创建一个引用:

self.hook = obj1

然后, setup_subUI 返回后,您执行以下操作:

self.hook = None

这会导致“覆盖”self.hook 作为对 None 的引用,因此先前的引用 (obj1) 被删除。由于那是唯一的引用,它会被删除,连同它的子元素。

然后您再次在 setup_subUI 中执行以下操作:

self.other_attribute_not_schedule = obj1

setup_subUI 返回时,下一行将按上述方式计算:

self.hook = None

这里的区别在于您没有覆盖 self.hook,因为它还不存在,并且 obj1 没有被删除,因为它的引用 (self.other_attribute_not_schedule) 仍然存在。

请注意,存在不同类型的引用(例如,将对象添加到持久列表中)并且它们可能并不总是显式的,尤其是对于 Qt 这样的复杂模块。

例如,将父对象添加到第一个对象的构造函数将防止删除,即使您执行self.hook = None

obj1 = QObject(self)

这是因为对象的所有权随后由 Qt 自己管理。
在很多情况下,Qt 会获得对象的所有权(必要时通过重新父对象),例如将小部件添加到布局然后将布局设置为另一个小部件时。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?