What's the correct pattern for threading in a python qt5 application?

烂漫一生 提交于 2019-12-12 01:54:26

问题


I'm trying to write a pyqt5 application with a long running, but not CPU intensive process. I'd like to be able to run it without hanging the UI, so I'm trying to use threading, but since it doesn't seem like I can just run a thread and have it stop after its gone through its code so that it can be run again, I've tried setting up the thread to wait for a variable to change before running.

I know this can't be the correct pattern for running long processes in a pyqt app.

import time
import threading
from PyQt5 import QtWidgets, uic


class MyApp(QtWidgets.QMainWindow):
    _run_thread = False

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = uic.loadUi('myapp.ui', self)

        self.ui.start_thread_button.clicked.connect(self._run_thread_function)

        self._thread = threading.Thread(target=self._run_thread_callback)
        self._thread.daemon = True
        self._thread.start()

        self.ui.show()

    def _run_thread_callback(self):
        while True:
            if self._run_thread:
                print("running thread code...")
                time.sleep(10)
                print("thread code finished")
                self._run_thread = False

    def _run_thread_function(self):
        print("starting thread...")
        self._run_thread = True


def main():
    app = QtWidgets.QApplication(sys.argv)
    MyApp()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

回答1:


Below is a simple demo showing how to start and stop a worker thread, and safely comminucate with the gui thread.

import sys
from PyQt5 import QtCore, QtWidgets

class Worker(QtCore.QThread):
    dataSent = QtCore.pyqtSignal(dict)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self._stopped = True
        self._mutex = QtCore.QMutex()

    def stop(self):
        self._mutex.lock()
        self._stopped = True
        self._mutex.unlock()

    def run(self):
        self._stopped = False
        for count in range(10):
            if self._stopped:
                break
            self.sleep(1)
            data = {
                'message':'running %d [%d]' % (
                    count, QtCore.QThread.currentThreadId()),
                'time': QtCore.QTime.currentTime(),
                'items': [1, 2, 3],
                }
            self.dataSent.emit(data)

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.edit = QtWidgets.QPlainTextEdit()
        self.edit.setReadOnly(True)
        self.button = QtWidgets.QPushButton('Start')
        self.button.clicked.connect(self.handleButton)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.edit)
        layout.addWidget(self.button)
        self._worker = Worker()
        self._worker.started.connect(self.handleThreadStarted)
        self._worker.finished.connect(self.handleThreadFinished)
        self._worker.dataSent.connect(self.handleDataSent)

    def handleThreadStarted(self):
        self.edit.clear()
        self.button.setText('Stop')
        self.edit.appendPlainText('started')

    def handleThreadFinished(self):
        self.button.setText('Start')
        self.edit.appendPlainText('stopped')

    def handleDataSent(self, data):
        self.edit.appendPlainText('message [%d]' %
            QtCore.QThread.currentThreadId())
        self.edit.appendPlainText(data['message'])
        self.edit.appendPlainText(data['time'].toString())
        self.edit.appendPlainText(repr(data['items']))

    def handleButton(self):
        if self._worker.isRunning():
            self._worker.stop()
        else:
            self._worker.start()

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 100, 400, 400)
    window.show()
    sys.exit(app.exec_())


来源:https://stackoverflow.com/questions/40539114/whats-the-correct-pattern-for-threading-in-a-python-qt5-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!