Как остановить работу приложения на pyqt5 без выхода из GUI python 3? (реализация кнопки Stop)
Коллеги, здравствуйте! Доделываю программу на pyqt5 и python 3, которая делает расчет по данным, вводимым с интерфейса, после чего сохраняет отчет и выводит результат на интерфейс. Все работает, за исключением кнопки Стоп, которая, по задумке должна остановить работу в случае, если пользователь заметил ошибку в вводимых значениях, или хочет их изменить.
Программа состоит из трех классов: форма, БЛ и приложение.
class Ui_Form(object):
def setupUi(self, Form):
...
self.stopBtn = QtWidgets.QPushButton(self.centralwidget)
self.stopBtn.setGeometry(QtCore.QRect(70, 320, 32, 32))
self.stopBtn.setText("")
self.stopBtn.setObjectName("stopBtn")
self.stopBtn.setIcon(QtGui.QIcon(QtGui.QPixmap('stop.png')))
self.stopBtn.setIconSize(QtCore.QSize(28, 28))
self.stopBtn.setEnabled(False)
...
class Creator(QtCore.QObject):
...
def prepare():
...
def calculation():
...
def generate_report():
...
def run(self):
prepare()
calculation()
generate_report()
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
self.ui = Ui_Form()
self.ui.setupUi(self)
...
# connect handler functions to button
self.ui.startBtn.clicked.connect(self.work)
self.ui.stopBtn.clicked.connect(self.stop_work)
# create thread
self.thread = QtCore.QThread()
# create object which will work thread
self.creator = Creator()
# move mosaic_creator th thread
self.creator.moveToThread(self.thread)
# start a thread
self.thread.started.connect(self.creator.run)
...
@pyqtSlot()
def stop_work(self):
print('press stop')
self.thread.quit()
self.thread.wait(5000)
self.thread.terminate()
Кнопка выглядит следующим образом и становится доступна только после старта процесса. Но при её нажатии программа продолжает работать (в консоли печатается "press stop").
Подскажите пожалуйста как сделать рабочую кнопку? Подозреваю, что можно реализовать её с помощью QProcess или QThreadPool, но примеров как это можно сделать пока не нашел.
Ответы (1 шт):
Решил задачу путем добавления флага (спасибо за наводку @Alexander Chernin). В рабочий класс добавил флаг, проверку которого осуществляю в рабочих функциях и вначале длительных циклов - если флаг=False, то работа не идет и цикл совершает итерации.
Применительно к коду, написанному в вопросе изменения выглядят так:
class Ui_Form(object):
def setupUi(self, Form):
...
self.stopBtn = QtWidgets.QPushButton(self.centralwidget)
self.stopBtn.setGeometry(QtCore.QRect(70, 320, 32, 32))
self.stopBtn.setText("")
self.stopBtn.setObjectName("stopBtn")
self.stopBtn.setIcon(QtGui.QIcon(QtGui.QPixmap('stop.png')))
self.stopBtn.setIconSize(QtCore.QSize(28, 28))
self.stopBtn.setEnabled(False)
...
class Creator(QtCore.QObject):
def __init__(self):
super().__init__()
self.isWork = False
def prepare():
if self.isWork:
...
def calculation():
for i in data:
if self.isWork:
...
def generate_report():
if self.isWork:
...
def run(self):
prepare()
calculation()
generate_report()
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
self.ui = Ui_Form()
self.ui.setupUi(self)
...
# connect handler functions to button
self.ui.startBtn.clicked.connect(self.work)
self.ui.stopBtn.clicked.connect(self.stop_work)
# create thread
self.thread = QtCore.QThread()
# create object which will work thread
self.creator = Creator()
# move mosaic_creator th thread
self.creator.moveToThread(self.thread)
# start a thread
self.thread.started.connect(self.creator.run)
...
@pyqtSlot()
def start_work(self):
self.creator.isWork = True
self.thread.start()
@pyqtSlot()
def stop_work(self):
self.creator.isWork = False
print('press stop')
self.thread.quit()
self.thread.wait(5000)
self.thread.terminate()
