我正在写一个基于 PySide2 的应用程序,其中包括一个QScrollArea
,其中包含许多QPixmap
图像(或更优:QLabel
的列表依次包含像素图)。该图像列表会随着时间的增长而变得很大,因此当达到一定数量时,我会定期从滚动区域中删除其中一些图像-效果很好。
但是,我确实给人的印象是,即使删除了一些图像,我的应用程序的内存消耗仍然相同。因此,删除标签小部件可能还不够。来自QLayout.removeWidget()
上的PySide2文档:
从布局中删除小部件 widget 。通话后,调用方有责任为小部件提供合理的几何形状,或将其放回布局中,或在必要时显式隐藏它。
为了删除小部件,我执行以下操作:
while self.images_scroll_layout.count() > MAX_IMAGES:
to_remove = self.images_scroll_layout.itemAt(self.images_scroll_layout.count() - 1)
self.images_scroll_layout.removeItem(to_remove)
to_remove.widget().deleteLater()
所以我的问题是:我是否需要手动销毁从布局中删除的标签/像素图,还是应该自动对其进行垃圾回收?
答案 0 :(得分:2)
要了解该操作,您必须具有以下明确的概念:
要验证,您可以使用以下代码,其中不会显示指示删除QObject的销毁信号。
from PySide2 import QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.add_button = QtWidgets.QPushButton(self.tr("Add"), clicked=self.add_widget)
self.remove_button = QtWidgets.QPushButton(
self.tr("Remove"), clicked=self.remove_widget
)
scrollarea = QtWidgets.QScrollArea(widgetResizable=True)
widget = QtWidgets.QWidget()
scrollarea.setWidget(widget)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.add_button)
lay.addWidget(self.remove_button)
lay.addWidget(scrollarea)
self.resize(640, 480)
self.label_layouts = QtWidgets.QVBoxLayout(widget)
self.counter = 0
def add_widget(self):
label = QtWidgets.QLabel(f"label {self.counter}")
self.label_layouts.addWidget(label)
self.counter += 1
def remove_widget(self):
item = self.label_layouts.itemAt(0)
if item is None:
return
widget = item.widget()
if widget is None:
return
widget.destroyed.connect(print)
print(f"widget: {widget} Parent: {widget.parentWidget()}")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
结论:不使用removeWidget()从内存中删除小部件,而仅使布局不处理该小部件,如果要删除小部件,则必须使用deleteLater()。
def remove_widget(self):
item = self.label_layouts.itemAt(0)
if item is None:
return
widget = item.widget()
if widget is None:
return
widget.destroyed.connect(print)
widget.deleteLater()