Jithu Jithu
Jithu Jithu

Reputation: 1

How to stop a thread using a button

We are creating an object detection project using Object detection API. We are train the program making pyqt5 GUI application. Trying to run the training part using thread. We want to stop the running thread using a push button. Here the code sample

class stopClass(QtCore.QThread):
    def __init__(self, parent=None):
        super(stopClass, self).__init__(parent)

    def startTrain(self):
    
        #changing directory
        os.chdir(r"c://tensorflow_1//models//research//object_detection")
        args3 = shlex.split('python train.py --logtostderr --train_dir=training/ -- 
        pipeline_config_path=training/faster_rcnn_inception_v2_pets.config')
        subprocess.run(args3, shell = True)
        return




    def run(self):
        self.startTrain()
    

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(701, 495)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.Annotation = QtWidgets.QPushButton(self.centralwidget)
        self.Annotation.setGeometry(QtCore.QRect(480, 10, 181, 41))
        self.Annotation.setToolTip("")
        self.Annotation.setObjectName("Annotation")
        self.Start_train = QtWidgets.QPushButton(self.centralwidget)
        self.Start_train.setGeometry(QtCore.QRect(480, 110, 181, 41))
        self.Start_train.setObjectName("Start_train")
        self.Stop_train = QtWidgets.QPushButton(self.centralwidget)
        self.Stop_train.setEnabled(False)
        self.Stop_train.setGeometry(QtCore.QRect(480, 160, 181, 41))
        self.Stop_train.setObjectName("Stop_train")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 701, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.Start_train.clicked.connect(self.starting)
   
       
   

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.Start_train.setText(_translate("MainWindow", "start train"))
        self.Stop_train.setText(_translate("MainWindow", "stop train"))
        


def starting(self):
    self.stopThread = stopClass()
    
    self.stopThread.start()
    self.Stop_train.setEnabled(True)
    
    self.Stop_train.clicked.connect(self.stopThread.exit)
    self.Start_train.setEnabled(False)

Upvotes: 0

Views: 59

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

In this case I do not see the need to use threads since it is enough to use QProcess that allows a simple handling of the execution of the script. On the other hand, do not modify the script generated by pyuic so my solution assumes that you must recreate that script that must be called gui.py:

import shlex
import sys

from PyQt5.QtCore import QObject, QProcess
from PyQt5.QtWidgets import QApplication, QMainWindow

from gui import Ui_MainWindow


class Manager(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._process = QProcess()
        working_directory = r"c://tensorflow_1//models//research//object_detection"
        self.process.setWorkingDirectory(working_directory)
        self.process.setProgram(sys.executable)
        args = shlex.split(
            "train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/faster_rcnn_inception_v2_pets.config"
        )
        self.process.setArguments(args)

    @property
    def process(self):
        return self._process

    def start(self):
        if self.process.state() == QProcess.NotRunning:
            self.process.start()

    def stop(self):
        if self.process.state() != QProcess.NotRunning:
            self.process.kill()


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)

        self.manager = Manager()
        self.Start_train.clicked.connect(self.manager.start)
        self.Stop_train.clicked.connect(self.manager.stop)
        self.manager.process.stateChanged.connect(self._handle_stateChanged)

    def _handle_stateChanged(self, state):
        self.Start_train.setEnabled(state != QProcess.Running)
        self.Stop_train.setEnabled(state == QProcess.Running)


def main():
    app = QApplication(sys.argv)

    w = MainWindow()
    w.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

Upvotes: 1

Related Questions