我正在写一个 PySide2-基于应用,其中包括 QScrollArea
盛产 QPixmap
图像(或更好的:一个列表 QLabel
的图片,而这些图片又包含了pixmaps)。) 随着时间的推移,图片列表可能会越来越多,所以当达到一定数量时,我定期从滚动区域中删除其中的一些图片--效果不错。
然而,我的印象是,即使删除了一些图片,我的应用程序的内存消耗仍然是一样的。所以删除标签部件可能还不够。从PySide2的文档中可以看到 QLayout.removeWidget()
:
移除小组件 小部件 的布局中。在此调用后,调用者有责任给小组件一个合理的几何形状,或将小组件放回布局中,或在必要时明确隐藏它。
为了删除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()
所以我的问题是: 我是否需要手动销毁我从布局中移除的labelspixmaps,或者它们应该被自动垃圾回收?
为了理解这个操作,你必须有以下清晰的概念。
为了验证,你可以使用下面的代码,当一个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()不是用来从内存中删除widget的,只是让布局不处理该widget,如果要删除一个widget,必须使用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()