当直接从文件而不是 QImage 制作时,PyQt 中的 QPixmaps 不会被正确清理

QPixmaps in PyQt don't get cleaned up properly when made directly from file and not from QImage

考虑以下代码:

from PyQt4 import QtCore, QtGui, QtNetwork, QtWebKit


class ImageView(QtGui.QGraphicsView):

    def __init__(self, file):
        super().__init__()
        self.setScene(QtGui.QGraphicsScene())
        f = QtGui.QPixmap(QtGui.QImage(file))
        # f = QtGui.QPixmap(file)
        item = QtGui.QGraphicsPixmapItem(f)
        self.scene().addItem(item)

    def mousePressEvent(self, event):
        self.scene().clear()

image = 'big.png'
app = QtGui.QApplication([])
view = ImageView(image)
view.show()
app.exec_()

这里我加载了一个大的(10000x10000px)图像并将其显示在QGraphicsView 中,然后可以通过单击鼠标清除场景。如果使用 f = QtGui.QPixmap(QtGui.QImage(file)) 行,则在清除场景后,内存使用量从 400 Mb 下降到 20,表明图像已从内存中清除。但是,如果我将该行替换为 f = QtGui.QPixmap(file),那么在执行相同操作后,内存使用量仍保持在 400 Mb。它也不会在以后重新分配——如果在清除场景后我用另一个大图像创建另一个 ImageView,则会分配另一个块。此外,当我直接从文件创建 QPixmap 时,我无法以任何方式释放内存 - 我尝试了 Python 的 deleteLaterdel 和 gc 模块。这在 PyQt 和 Pyside 中都会发生。为什么会这样?

采用文件名的 QPixmap 方法将通过 QPixmapCache 进行自动缓存。所以应该可以像这样释放内存:

QPixmapCache.clear()

Qt 文档指出 QPixmapCache 的桌面系统缓存限制为 10mb。但是,在实践中可能会超过此限制。其原因有些模糊,但查看源代码显示 Qt 使用 QCache, and sets its maxCost to cache_limit * 1024. However, the docs for totalCost 表示可能会超出隐式共享 类(例如 QPixmap)。