Python QThread в графическом интерфейсе - PullRequest
0 голосов
/ 10 мая 2019

Я пытаюсь следовать этому руководству , чтобы позволить долговременному методу работать в отдельном потоке. Функциональность работает, но она по-прежнему вызывает зависание GUI во время работы метода. Я что-то упустил, что позволило бы запустить это в отдельном потоке?

from PySide2.QtWidgets import QDialog, QApplication, QMainWindow
from PySide2.QtCore import Qt, QThread, SIGNAL
import time

class MyClient():
    '''Members of this class get passed to the QThread subclass instance in order to "doSomething" in a separate thread'''
    def __init__(self, name):
        self.name = name

    def doSomething(self):
        time.sleep(10) # but really do something more useful
        return self.name

class WorkerThread(QThread):
    '''Supposed to perform operation in a separate thread so GUI remains responsive.'''

    def __init__(self, client):
        super().__init__()
        self.client = client

    def __del__(self):
        self.wait()

    def run(self):
        print("Running!!!")
        return self.client.doSomething()

class MyForm(QMainWindow):
    def __init__(self, clients):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.clients = clients

        # Connect button to method
        self.ui.btn_fetch.clicked.connect(self.fetch)

        self.show()
        self.fetch()

    def printName(self, name):
        print(name)

    def fetch(self):
        for client in self.clients:
            self.workerThread = WorkerThread(client)

            self.connect(self.workerThread, SIGNAL("printName(QString)"), self.printName)

            print("Starting thread")
            self.workerThread.start()
            # GUI becomes unresponsive here until the workerThread finishes.
            print("Thread started")

if __name__ == "__main__":

    clients = [MyClient('foo'), MyClient('bar'), MyClient('baz')]

    app = QApplication(sys.argv)
    w = MyForm(clients)
    w.show()
    sys.exit(app.exec_())

1 Ответ

1 голос
/ 10 мая 2019

Вот рабочий пример использования сигналов PyQt5 / PySide2:

import sys
import time

from PyQt5.QtWidgets import QDialog, QApplication, QMainWindow
from PyQt5.QtCore import Qt, QThread, QObject, pyqtSignal

# If you need Pyside2 like in your example (untested):
# from PySide2.QtWidgets import QDialog, QApplication, QMainWindow
# from PySide2.QtCore import Qt, QThread, QObject, Signal


class MyClient:
    """Members of this class get passed to the QThread subclass instance
    in order to "doSomething" in a separate thread"""
    def __init__(self, name):
        self.name = name

    def doSomething(self):
        time.sleep(10)  # but really do something more useful
        return self.name


class WorkerThread(QThread):
    didSomething = pyqtSignal(str)

    """Supposed to perform operation in a separate thread so GUI remains responsive."""
    def __init__(self, client):
        super().__init__()
        self.client = client

    def run(self):
        print("Running!!!")
        self.didSomething.emit(self.client.doSomething())


class MyForm(QMainWindow):
    def __init__(self, clients):
        super().__init__()
        self.clients = clients

        # self.ui = Ui_MainWindow()
        # self.ui.setupUi(self)

        # Connect button to method
        # self.ui.btn_fetch.clicked.connect(self.fetch)

        self.workerThreads = []

        self.fetch()

    def printName(self, name):
        print(name)

    def removeThread(self, workerThread):
        def removeWorkerThread():
            self.workerThreads.remove(workerThread)
            print('Thread removed. Total active threads: {}'.format(len(self.workerThreads)))
        return removeWorkerThread

    def fetch(self):
        for client in self.clients:
            workerThread = WorkerThread(client)
            workerThread.didSomething.connect(self.printName)
            workerThread.finished.connect(self.removeThread(workerThread))
            self.workerThreads.append(workerThread)

            print("Starting thread")
            workerThread.start()

            # GUI becomes unresponsive here until the workerThread finishes.
            print("Thread started")


if __name__ == "__main__":
    myClients = [MyClient('foo'), MyClient('bar'), MyClient('baz')]

    app = QApplication(sys.argv)
    w = MyForm(myClients)
    w.show()
    sys.exit(app.exec_())
...