Как остановить работу приложения на 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 шт):

Автор решения: user330377

Решил задачу путем добавления флага (спасибо за наводку @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()
→ Ссылка