Python - PyQt:QThread 完成后继续

Python - PyQt : Continue after a QThread is finished

我在 QThread 中有一个 for 循环,它是通过按钮从主 GUI 启动的。当 for 循环结束时,我想回到主线程(在 Gui class 内)并做其他事情。 据我了解,应该使用 join 方法等待线程完成。就我而言,MyThread 似乎永远不会完成。

import sys
from PyQt5 import QtCore
import PyQt5.QtWidgets as QtW
from PyQt5.QtCore import QThread

class MyWindow(QtW.QMainWindow):

  def __init__(self):
    super().__init__()
    self.setWindowTitle('MyWindow')
    self._main = QtW.QWidget()
    self.setCentralWidget(self._main) 
    self.button = QtW.QPushButton('Do it', self)
    self.button.clicked.connect(self.MyMethod)
    self.layout = QtW.QGridLayout(self)
    self.layout.addWidget(self.button)
    self.setLayout(self.layout)


  def MyMethod(self):
    self.n = 5
    self.loadthread = MyThread(self.n)
    self.loadthread.start()
    self.loadthread.join() # Will wait for the thread until it finishes its task
    print('thread finished')


class MyThread(QThread):

    def __init__(self, n):
        QThread.__init__(self)
        self.n = n

    def run(self):
        for i in range(self.n):
            print(i)
        print('cycle finished')


if __name__ == '__main__':
    app = QtCore.QCoreApplication.instance() # checks if QApplication already exists 
    if app is None: # create QApplication if it doesnt exist 
        app = QtW.QApplication(sys.argv)
    mainGui = MyWindow()
    mainGui.show()
    app.aboutToQuit.connect(app.deleteLater)
    app.exec_()

cose 的输出是

0
1
2
3
4
cycle finished

并且 print('thread finished') 从未达到。

QThread 没有 join() 方法,因此您的应用程序应该意外退出并指向以下错误消息。

QLayout: Attempting to add QLayout "" to MyWindow "", which already has a layout
QWidget::setLayout: Attempting to set QLayout "" on MyWindow "", which already has a layout
0
1
2
3
Traceback (most recent call last):
  File "main.py", line 24, in MyMethod
    self.loadthread.join() # Will wait for the thread until it finishes its task
AttributeError: 'MyThread' object has no attribute 'join'
4
cycle finished
Aborted (core dumped)

如果你想在完成线程执行后执行一些任务,你必须使用QThreadfinished信号:

import sys
from PyQt5 import QtCore, QtWidgets


class MyWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MyWindow')
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main) 
        self.button = QtWidgets.QPushButton('Do it')
        self.button.clicked.connect(self.my_method)
        layout = QtWidgets.QGridLayout(self._main)
        layout.addWidget(self.button)
        layout.addWidget(self.button)

    @QtCore.pyqtSlot()
    def my_method(self):
        self.n = 5
        self.loadthread = MyThread(self.n, self)
        self.loadthread.finished.connect(self.on_finished)
        self.loadthread.start()

    @QtCore.pyqtSlot()
    def on_finished(self):
        print('thread finished')


class MyThread(QtCore.QThread):
    def __init__(self, n, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.n = n

    def run(self):
        for i in range(self.n):
            print(i)
        print('cycle finished')


if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()
    if app is None: 
        app = QtWidgets.QApplication(sys.argv)
    mainGui = MyWindow()
    mainGui.show()
    app.aboutToQuit.connect(app.deleteLater)
    sys.exit(app.exec_())