【问题标题】:Python QThread in GUIGUI 中的 Python QThread
【发布时间】:2019-05-10 01:21:53
【问题描述】:

我正在尝试关注this guide,让长时间运行的方法在单独的线程中运行。该功能正在运行,但在方法运行时仍会导致 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_())

【问题讨论】:

    标签: python python-3.x pyqt5 qthread pyside2


    【解决方案1】:

    这是一个使用 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_())
    

    【讨论】:

    • 感谢伊斯玛!我会在星期一试试这个。
    • 经过测试并围绕信号槽架构进行了很多思考,它正在工作。非常感谢您的帮助!
    猜你喜欢
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 2013-04-21
    • 2019-10-05
    • 1970-01-01
    • 2021-12-25
    相关资源
    最近更新 更多