Pyqt5在QAction上停止QThread worker

时间:2018-09-18 14:25:00

标签: python-3.x pyqt pyqt5

您好,我有QTheard worker,首先单击QAction。

....
self.start_update = QAction('&Start', self)
self.start_update.triggered.connect(self._start_thread)
self.stop_update.setVisible(True)
self.stop_update.triggered.connect(self._stop_thread)
self.stop_update.setVisible(False)
...

...
def _start_thread(self):
   self.start_update.setVisible(False)
   self.stop_update.setVisible(True)
   self.myworker.start()
...

...
def _stop_thread(self):
   self.myworker.stop() # That close app with error
   self.stop_update.setVisible(False)
   self.start_update.setVisible(True)
...

请帮助正确关闭终止Worker。 Atm worker具有__del__run(逻辑)方法。也许需要添加一些方法来正确关闭工作程序?

1 个答案:

答案 0 :(得分:1)

您的应用程序可能看起来像这样:

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class AThread(QThread):
    threadSignalAThread = pyqtSignal(int)
    def __init__(self):
        super().__init__()

    def run(self):
        count = 0
        while count < 1000:
            QThread.msleep(200)
            count += 1
            self.threadSignalAThread.emit(count)


class MsgBoxAThread(QDialog):
    def __init__(self):
        super().__init__()
        layout     = QVBoxLayout(self)
        self.label = QLabel("")
        layout.addWidget(self.label)
        close_btn  = QPushButton("Close window")
        layout.addWidget(close_btn)
        close_btn.clicked.connect(self.close) 
        self.setGeometry(900, 300, 400, 80)
        self.setWindowTitle('MsgBox AThread(QThread)')


class Example(QMainWindow):
    def __init__(self, parent=None, *args):
        super().__init__(parent, *args)  
        self.setWindowTitle("Pyqt5 stop QThread worker on QAction")
        self.setGeometry(550, 300, 300, 300)
        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)        
        layout   = QVBoxLayout(centralWidget)
        self.lbl = QLabel("Start")
        layout.addWidget(self.lbl)

        bar       = self.menuBar()
        barThread = bar.addMenu('Thread')
        quit      = bar.addMenu('Quit')
        quit.aboutToShow.connect(app.quit)         

        self.start_update = QAction('&Start', self)
        self.start_update.setShortcut('Ctrl+S')      
        self.start_update.triggered.connect(self._start_thread)

        self.stop_update = QAction('Sto&p', self)
        self.stop_update.setShortcut('Ctrl+P')
        self.stop_update.setVisible(False)
        self.stop_update.triggered.connect(self._stop_thread)

        barThread.addAction(self.start_update)
        barThread.addAction(self.stop_update)

        self.msg      = MsgBoxAThread()  
        self.myworker = None
        self.counter  = 0
        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.recurring_timer)   
        self.timer.start()        
        self.show()

    def recurring_timer(self):
        self.counter += 1
        self.lbl.setText(" Do something in the GUI: <b> %d </b>" % self.counter)        

    def _start_thread(self):
        self.start_update.setVisible(False)
        self.stop_update.setVisible(True)
        self.myworker = AThread() 
        self.myworker.threadSignalAThread.connect(self.on_threadSignalAThread)
        self.myworker.finished.connect(self.finishedAThread)
        self.myworker.start()

    def finishedAThread(self):
        self.myworker = None
        self.start_update.setVisible(True)
        self.stop_update.setVisible(False)

    def on_threadSignalAThread(self, value):
        self.msg.label.setText(str(value))
        if not self.msg.isVisible():        
            self.msg.show() 

    def _stop_thread(self):
        self.stop_update.setVisible(False)
        self.start_update.setVisible(True)
        self.myworker.terminate()         
        self.myworker = None

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Question',
            "Are you sure you want to close the application?",
             QMessageBox.Yes,
             QMessageBox.No)
        if reply == QMessageBox.Yes:
            if self.myworker:
                self.myworker.quit()
            del self.myworker
            self.msg.close()

            super(Example, self).closeEvent(event)
        else:
            event.ignore()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex  = Example()
    #ex.show()
    sys.exit(app.exec_())  

enter image description here