PyQt/PySide 中需要deleteLater()吗?

问题描述 投票:0回答:2

既然Python中已经有了垃圾收集器,那么在PyQt/PySide中

deleteLater()
还有必要吗?

python qt pyqt pyside
2个回答
23
投票

这取决于你所说的“必要”是什么意思。

如果(例如)关闭小部件时不小心,应用程序可能会潜在地消耗大量内存。基于 QObject 的类被设计为(可选)在层次结构中链接在一起。当删除顶级对象时,Qt 也会自动删除其所有子对象。但是,当关闭小部件(QObject 的子类)时,只有设置了 Qt.WA_DeleteOnClose 属性(默认情况下通常不会),才会发生自动删除。

为了说明这一点,请尝试重复打开和关闭此演示脚本中的对话框,并观察全局对象列表如何增长:

import sys from PyQt5 import QtCore, QtWidgets class Window(QtWidgets.QWidget): def __init__(self): super().__init__() self.checkbox = QtWidgets.QCheckBox('Delete') self.button = QtWidgets.QPushButton('Open', self) self.button.clicked.connect(self.openDialog) layout = QtWidgets.QHBoxLayout(self) layout.addWidget(self.checkbox) layout.addWidget(self.button) def openDialog(self): widget = QtWidgets.QDialog(self) if (self.checkbox.isChecked() and not widget.testAttribute(QtCore.Qt.WA_DeleteOnClose)): widget.setAttribute(QtCore.Qt.WA_DeleteOnClose) for child in self.findChildren(QtWidgets.QDialog): if child is not widget: child.deleteLater() label = QtWidgets.QLabel(widget) button = QtWidgets.QPushButton('Close', widget) button.clicked.connect(widget.close) layout = QtWidgets.QVBoxLayout(widget) layout.addWidget(label) layout.addWidget(button) objects = self.findChildren(QtCore.QObject) label.setText('Objects = %d' % len(objects)) print(objects) widget.show() if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) window = Window() window.setGeometry(500, 300, 100, 50) window.show() sys.exit(app.exec_())
使用 PyQt/PySide,对象所有权有两个方面:Python 部分和 Qt 部分。通常,删除对对象的最后一个 Python 引用不足以完全清理,因为 Qt 端仍然可能保留有引用。

一般来说,Qt 倾向于

隐式删除对象。因此,如果您的应用程序创建和删除大量 QObject(或打开和关闭大量 QWidget),如果内存使用量是一个问题,您“可能”需要采取措施显式删除它们。 更新

只是为了补充上面关于对象所有权的几点。有时,可能会保留对对象的 Python 引用,而 Qt 部分会被删除。发生这种情况时,您将看到如下错误:

运行时错误:底层 C/C++ 对象已被删除

通常,Qt 文档会给出一些关于何时可能发生这种情况的提示。例如,

QAbstractItemView.setModel
给出了这个警告:

视图不拥有模型的所有权,除非它是模型的父对象...

这告诉您必须保留对该对象的 Python 引用,或者将合适的父对象传递给该对象的构造函数,因为 Qt 并不总是自动重新为其设置父对象。


1
投票
的一个应用程序可以自行清理,即安排删除 QObject(例如在线程中)以从对象本身内部释放资源。

这里的
示例

有人正在将它与信号线程结合使用。已完成。不过,它可能仅限于信号繁重的情况。

© www.soinside.com 2019 - 2024. All rights reserved.