似乎我在应用程序中运行线程时遇到问题,如下所示:在我的MainForm类中,我有:
.
.
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类的以下部分:
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
并添加选项卡。然后可以将第一个移动到线程池,并且每次加载像素图时,都可以使用信号自动调用第二个。例如:
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)