PyQt5;使用 QRunnable 和 QThreadPool 的线程问题
PyQt5; problem with threading using QRunnable and QThreadPool
我的应用程序中的 运行ning 线程似乎有问题,如下所示:
在我的 MainForm class 我有:
.
.
self.threadPool = QtCore.QThreadPool()
self.threadPool.setMaxThreadCount(4)
.
.
def openFileFcn(self):
worker = **Worker**(self, **self.ImageViewer.showImages**, self.files)
self.threadPool.start(worker)
其中 Worker 是一个包装器 QRunnable,定义为:
class Worker(QtCore.QRunnable):
def __init__(self, fn, *args, **kwargs):
QtCore.QRunnable.__init__(self)
self.fn = fn
self.args = args
self.kwargs = kwargs
def run(self) -> None:
self.fn(*self.args, **self.kwargs)
和self.ImageViewer.showImages指的是ImageViewer的以下部分class:
def loadImg(self, file):
tabName = str()
if len(file) > 15: tabName = file[0:13] + "..."
widget = ImageViewer()
localPath = os.path.abspath(file)
localPath = QtCore.QDir().filePath(localPath)
pixmap = QtGui.QPixmap(localPath)
widget.setImage(pixmap)
self.tabwidget.addTab(widget, self.mainFormHandle.sharedData.imgIcon, tabName)
self.tabwidget.setCurrentIndex(self.tabwidget.currentIndex() + 1)
def **showImages**(self, files):
files = [file.lower() for file in files]
for file in files:
self.loadImg(file)
当我 运行 这段代码时,什么都没有发生。它只是冻结,一段时间后应用程序关闭,退出代码为 -1073740791 (0xC0000409)。您认为原因是什么?
问题似乎是您正试图从主线程以外的另一个线程创建小部件。您只能从主线程创建小部件,但由于 loadImg()
创建了多个小部件,从线程池调用它会使您的应用程序崩溃。解决这个问题的一种方法是将 loadImg()
分成两种方法,一种方法加载像素图,另一种方法创建 ImageViewer
s 并添加选项卡。然后可以将第一个移至线程池,并且可以使用信号在每次加载像素图时自动调用第二个。例如:
class TabArea(QtWidgets.QWidget):
pixmap_loaded = QtCore.pyqtSignal(str, QtGui.QPixmap)
def __init__(self, parent=None):
...
self.pixmap_loaded.connect(self.addTab)
def loadImg(self, file):
localPath = os.path.abspath(file)
localPath = QtCore.QDir().filePath(localPath)
pixmap = QtGui.QPixmap(localPath)
# emit pixmap and file name
self.pixmap_loaded.emit(file, pixmap)
def addTab(self, file, pixmap):
tabName = str()
if len(file) > 15: tabName = file[0:13] + "..."
widget = ImageViewer()
widget.setImage(pixmap)
self.tabwidget.addTab(widget, self.mainFormHandle.sharedData.imgIcon, tabName)
self.tabwidget.setCurrentIndex(self.tabwidget.currentIndex() + 1)
def showImages(self, files):
files = [file.lower() for file in files]
for file in files:
self.loadImg(file)
我的应用程序中的 运行ning 线程似乎有问题,如下所示: 在我的 MainForm class 我有:
.
.
self.threadPool = QtCore.QThreadPool()
self.threadPool.setMaxThreadCount(4)
.
.
def openFileFcn(self):
worker = **Worker**(self, **self.ImageViewer.showImages**, self.files)
self.threadPool.start(worker)
其中 Worker 是一个包装器 QRunnable,定义为:
class Worker(QtCore.QRunnable):
def __init__(self, fn, *args, **kwargs):
QtCore.QRunnable.__init__(self)
self.fn = fn
self.args = args
self.kwargs = kwargs
def run(self) -> None:
self.fn(*self.args, **self.kwargs)
和self.ImageViewer.showImages指的是ImageViewer的以下部分class:
def loadImg(self, file):
tabName = str()
if len(file) > 15: tabName = file[0:13] + "..."
widget = ImageViewer()
localPath = os.path.abspath(file)
localPath = QtCore.QDir().filePath(localPath)
pixmap = QtGui.QPixmap(localPath)
widget.setImage(pixmap)
self.tabwidget.addTab(widget, self.mainFormHandle.sharedData.imgIcon, tabName)
self.tabwidget.setCurrentIndex(self.tabwidget.currentIndex() + 1)
def **showImages**(self, files):
files = [file.lower() for file in files]
for file in files:
self.loadImg(file)
当我 运行 这段代码时,什么都没有发生。它只是冻结,一段时间后应用程序关闭,退出代码为 -1073740791 (0xC0000409)。您认为原因是什么?
问题似乎是您正试图从主线程以外的另一个线程创建小部件。您只能从主线程创建小部件,但由于 loadImg()
创建了多个小部件,从线程池调用它会使您的应用程序崩溃。解决这个问题的一种方法是将 loadImg()
分成两种方法,一种方法加载像素图,另一种方法创建 ImageViewer
s 并添加选项卡。然后可以将第一个移至线程池,并且可以使用信号在每次加载像素图时自动调用第二个。例如:
class TabArea(QtWidgets.QWidget):
pixmap_loaded = QtCore.pyqtSignal(str, QtGui.QPixmap)
def __init__(self, parent=None):
...
self.pixmap_loaded.connect(self.addTab)
def loadImg(self, file):
localPath = os.path.abspath(file)
localPath = QtCore.QDir().filePath(localPath)
pixmap = QtGui.QPixmap(localPath)
# emit pixmap and file name
self.pixmap_loaded.emit(file, pixmap)
def addTab(self, file, pixmap):
tabName = str()
if len(file) > 15: tabName = file[0:13] + "..."
widget = ImageViewer()
widget.setImage(pixmap)
self.tabwidget.addTab(widget, self.mainFormHandle.sharedData.imgIcon, tabName)
self.tabwidget.setCurrentIndex(self.tabwidget.currentIndex() + 1)
def showImages(self, files):
files = [file.lower() for file in files]
for file in files:
self.loadImg(file)