Я смотрю на создание программы с PyQt5 GUI.Программа начнется с пользовательского интерфейса с многочисленными кнопками.Эти кнопки будут использоваться для открытия других программ / завершенных длительных задач.Я знаю, что мне нужно использовать QThread, но я не уверен, как структурировать программы так, чтобы они правильно масштабировались.
Я занимался этим целую вечность и прочитал множество постов / руководств.Большинство склоняется по маршруту подклассов.Раньше мне удавалось создать рабочую программу с подклассами QThread, но с тех пор я читал, что эта методология не является предпочтительной.
У меня такое чувство, что я должен создать универсальный рабочий и передать функцию с* args и ** kwargs, но этого пока нет в моем наборе навыков.
Я изначально создал поток для каждой кнопки во время инициализации GUI, но казалось, что он скоро выйдет из-под контроля.
В настоящее время я нахожусь на стадии создания потока под слотом, подключенным к сигналу button.clicked.Я не уверен, должен ли я тогда иметь работника для каждой кнопки, или я могу / должен сделать общего работника и передать функцию.Примечание: я пытался сделать это, но не смог этого сделать.
#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стрелять, не делая их в основном на заказ сигналов.Это одна из причин, по которой я думаю, что поступаю неправильно.