使用 QlistW 减少 RAM 使用 [关闭]
Posted
技术标签:
【中文标题】使用 QlistW 减少 RAM 使用 [关闭]【英文标题】:Reducing RAM usage with QlistW [closed] 【发布时间】:2022-01-22 19:18:49 【问题描述】:我正在尝试以图标模式将 100,000 张图像加载到 QtWidgets.QListWidget
中。我知道这是大量照片,但我需要将它们全部加载,因为我正在制作一个图像查看应用程序。我正在通过QtGui.QIcon
加载所有图像,并且它需要存储所有这些图像的内存量很大。有谁知道如何以不同方式加载这些图像以减少我正在使用的 RAM 量或更改设置以减少 RAM?
import sys
import CustomWidgets as cw
import platform
from PyQt5 import QtCore, QtGui, QtWidgets
import os
import threading
# GUI FILE
from PhotosPage import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# connect tab Pages
self.ui.PageButton_Photos.clicked.connect(lambda: self.ui.stackedWidget.setCurrentWidget(self.ui.PhotosPage))
self.ui.PageButton_Albums.clicked.connect(lambda: self.ui.stackedWidget.setCurrentWidget(self.ui.AlbumsPage))
self.ui.PageButton_People.clicked.connect(lambda: self.ui.stackedWidget.setCurrentWidget(self.ui.PeoplePage))
self.ui.PageButton_Groups.clicked.connect(lambda: self.ui.stackedWidget.setCurrentWidget(self.ui.GroupsPage))
self.ui.AlbumInfoFrame.hide()
# # Create album Cover - test
# cw.AlbumCover(self)
self.ui.listWidget.setIconSize(QtCore.QSize(128, 128))
threading.Thread(target=self.loadImgs, name="Loading Images").start()
self.show()
def loadImgs(self):
for i in os.listdir("D:/iPhone Pics"):
item = QtWidgets.QListWidgetItem()
photo = QtGui.QIcon("D:/iPhone Pics/"+i)
item.setIcon(photo)
self.ui.listWidget.addItem(item)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
【问题讨论】:
如果您正在加载所有图像,程序显然需要全部大小。没有简单的解决方案,每个画廊类型的程序都有自己的处理方式,通过使用自定义缓存和优化来提高性能并避免过多的内存使用。您必须自己找到它,并且您可能需要使用带有 QListView 的自定义模型(它可以使用 QListWidget 来完成,但您需要仔细实现项目委托)。此外,您应该从不从另一个线程访问 UI 元素。 不必一次加载 100,000 张图像。图像查看器永远无法真正显示那么多图像,因为屏幕上没有足够的空间。您应该只加载足够的图像来填充显示区域(加上两边的几页),并删除该范围之外的所有先前加载的图像以限制内存使用。见this question 和this pyqt5 example。 【参考方案1】:这里遇到了两个主要问题,首先,您尝试一次加载太多图像,这导致 CPU 速度变慢,其次您正在加载太大的文件。 -> 像素宽度和高度太大,而不是文件大小。
文件大小:
在我的例子中,我加载了 100,000 张分辨率为 4k 的图像,这是不必要的,因为我的图标只有 300 x 175。要解决此问题,您可以在 PIL 中打开图像并调整图像大小,然后将其带入到 Qt 以减少它使用的内存量。
image = Image.open("file Location")
image = image.resize((300,150),Image.ANTIALIAS)
# Turn PIL image to Qt Image
qImage = ImageQt(image)
pixmap = QtGui.QPixmap.fromImage(qImage)
Icon = QtGui.QIcon(pixmap)
或者您可以保存一个较小版本的文件,然后在使用更快的图标时加载它。
延迟加载:
在延迟加载方面,您可以使用如下所示的模型一次加载一行按钮。
import sys
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt
import os
class TestListModel(QtCore.QAbstractListModel):
def __init__(self, parent=None):
QtCore.QAbstractListModel.__init__(self, parent)
self.list = parent
self.fileList = os.listdir('P:/PhotoSorterInfo/MiniPhotos')
def rowCount(self, index):
return len(self.fileList)
def data(self, index, role):
if role == Qt.DisplayRole:
if not self.list.indexWidget(index):
button = QtWidgets.QPushButton()
button.setIcon(QtGui.QIcon("P:/PhotoSorterInfo/MiniPhotos/" + self.fileList[index.row()]))
button.setIconSize(QtCore.QSize(300, 300))
self.list.setIndexWidget(index, button)
return QtCore.QVariant()
if role == Qt.SizeHintRole:
return QtCore.QSize(300, 300)
def columnCount(self, index):
pass
def main():
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QWidget()
list = QtWidgets.QListView()
model = TestListModel(list)
list.setModel(model)
list.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
list.setViewMode(QtWidgets.QListView.IconMode)
list.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
list.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
list.setResizeMode(QtWidgets.QListView.Adjust)
list.setViewMode(QtWidgets.QListView.IconMode)
list.setObjectName("PhotosFrame")
layout = QtWidgets.QVBoxLayout(window)
layout.addWidget(list)
window.setLayout(layout)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
【讨论】:
以上是关于使用 QlistW 减少 RAM 使用 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章