您应该能够使用 QThreadPool 和一些 QRunnables 来执行此操作,它们包装了加载像素图的代码。比如:
from PyQt5 import QtCore, QtGui
class PixmapLoader(QtCore.QRunnable):
def __init__(self, filename):
super().__init__()
self.filename = filename
def run(self):
# Load pixmap at filename
# ...
# then emit in a signal
loaded.emit(pixmap)
loaded = QtCore.pyqtSignal(QtGui.QPixmap)
然后在主应用程序的某个地方,创建一个线程池,运行加载对象,并处理它们的信号。
pool = QtCore.QThreadPool()
loaders = [PixmapLoader(filename) for filename in filenames]
for loader in loaders:
loader.loaded.connect(handle_new_pixmap)
pool.start(loader)
def handle_new_pixmap(QtGui.QPixmap):
# do stuff with pixmap
这个我没试过,但是因为Qt是处理线程的,所以应该可以很好的利用多线程。
编辑
如 cmets 中所述,这是行不通的。我忘记了QRunnable 不继承QObject,并且QPixmaps 不能在主线程之外创建。但是使用图像加载器对象非常简单,将其移动到一个或多个后台线程,在其中加载QImage,然后将其发送到主线程供以后使用。这是经过测试的代码,它将执行基本操作,加载当前目录中的所有 PNG 文件。
#!/usr/bin/env python3
import os
from PyQt5.QtCore import pyqtSignal, QObject, QThread
from PyQt5.QtGui import QImage
from PyQt5.QtWidgets import QApplication
class ImageLoader(QObject):
loaded = pyqtSignal(str, QImage)
def __init__(self, filename):
super().__init__()
self.filename = filename
def on_load_signal(self):
img = QImage(self.filename)
self.loaded.emit(self.filename, img)
class LoaderManager(QObject):
request_img_load = pyqtSignal()
def __init__(self):
super().__init__()
self.loaders = list(map(ImageLoader,
filter(lambda f: f.endswith('.png'), os.listdir())))
self.bg_thread = QThread()
for loader in self.loaders:
self.request_img_load.connect(loader.on_load_signal)
loader.loaded.connect(self.handle_img_loaded)
loader.moveToThread(self.bg_thread)
self.bg_thread.start()
def __del__(self):
self.bg_thread.quit()
def load_all(self):
self.request_img_load.emit()
def handle_img_loaded(self, name, img):
print('File {} of size {} loaded'.format(name, img.byteCount()))
if __name__ == '__main__':
app = QApplication([])
manager = LoaderManager()
manager.load_all()