如何在不子类化 QThread 的情况下构建大型 pyqt5 GUI,并使用 QPushButton 执行长时间运行的任



我正在考虑创建一个带有PyQt5 GUI的程序。该程序将从带有许多按钮的 UI 开始。这些按钮将用于打开其他程序/已完成长时间运行的任务。我知道我需要使用 QThread,但我不确定如何构建程序以使其正确扩展。

我已经在这个领域工作了很长时间,并阅读了许多帖子/教程。大多数人倾向于子类化路线。过去,我设法创建了一个工作程序子类化 QThread,但后来我读到这种方法不是首选。

我有一种感觉,我应该创建一个通用的工人,并传递一个带有 *args 和 **kwargs 的函数,但这还不在我的技能集中。

我最初在 GUI 初始化期间为每个按钮创建了一个线程,但这似乎很快就会失控。

我目前正处于在连接到按钮的插槽下创建线程的阶段。我不确定我是否必须为每个按钮配备一个 worker ,或者我是否可以/应该创建一个通用工作线程并传入一个函数。注意:我尝试这样做,但无法做到。

#Import standard modules
import sys
#Import third-party modles
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QVBoxLayout, QWidget
class Worker(QObject):
#Custom signals?? or built-in QThread signals?
started = pyqtSignal()    
finished = pyqtSignal()
def __init__(self): 
super().__init__()
self.started.emit()
@pyqtSlot()
def do_something(self):
for _ in range(3):
print('Threading...')
QThread.sleep(1)
self.finished.emit()
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.initUi()
def initUi(self):
#Create GUI
self.centralWidget  = QWidget()
self.setCentralWidget(self.centralWidget )  
self.vertical_layout = QVBoxLayout(self.centralWidget)
self.setWindowTitle('QThread Test')
self.setGeometry(300, 300, 300, 50)
self.button1=QPushButton("Task 1", self, clicked=self._task1_clicked)
self.button2=QPushButton("Task 2", self, clicked=self._task2_clicked)
self.vertical_layout.addWidget(self.button1)
self.vertical_layout.addWidget(self.button2)
self.vertical_layout.addStretch()
def _task1_clicked(self):
print('task1 clicked')
#Create the worker
self.my_worker = Worker()          
#Create thread; needs to be done before connecting signals/slots
self.task1_thread = QThread()
#Move the worker to the thread
self.my_worker.moveToThread(self.task1_thread)        
#Connect worker and thread signals to slots
self.task1_thread.started.connect(self._thread_started)
self.task1_thread.started.connect(self.my_worker.do_something)
self.my_worker.finished.connect(self._thread_finished) 
#Start thread
self.task1_thread.start() 
def _task2_clicked(self):
print('task2 clicked')
def _thread_started(self):
print('thread started')
def _thread_finished(self):
print('thread finished')
self.my_worker.isRunning = False
self.task1_thread.quit()
self.task1_thread.wait()
print('The thread is running: ' + str(self.task1_thread.isRunning()))

if __name__ == '__main__':
app = QApplication(sys.argv)
form = Window()
form.show()
app.exec_()

以上似乎有效,但我觉得我偶然发现了它,这不是这样做的正确方法。如果完全错误,我不希望这成为我的"首选"方法。与一个按钮/一个任务程序相比,我希望能够生成更复杂的(更多按钮做事(程序。

此外,我似乎无法在不基本上使它们成为定制信号的情况下触发 QThread 启动和完成信号。这是我认为我做错了的原因之一。

from PyQt5 import QtCore
class AsyncTask(QtCore.QThread):
taskDone = QtCore.pyqtSignal(dict)
def __init__(self, *, task, callback=None, parent = None):
super().__init__(parent)
self.task = task
if callback != None:
self.taskDone.connect(callback)
if callback == None:
callback = self.callback
self.start()
def run(self):
try:
result = self.task()
print(result)
self.taskDone.emit(result)
except Exception as ex:
print(ex)
def callback(self):
print('callback')

请尝试上面的代码,像这样调用: AsyncTask(task=yourTaskFunction, callback=yourCallbackFunction(

最新更新