Python - PyQt: продолжить после завершения QThread - PullRequest
0 голосов
/ 28 сентября 2018

У меня есть цикл for в QThread, который запускается из основного графического интерфейса через кнопку.Когда цикл for закончен, я бы хотел вернуться к основному потоку (который находится внутри класса Gui) и заняться чем-то другим.Насколько я понял, нужно использовать метод 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') никогда не достигается.

1 Ответ

0 голосов
/ 28 сентября 2018

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)

Если вы хотите выполнить какое-либо задание после его завершенияпоток, который вы должны использовать finished сигнал QThread:

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_())
...