Alvin Lorejas
Alvin Lorejas

Reputation: 115

How to stop a non-responding mainwindow in pyqt5 due to long loops with a push button?

Problem I have a long running loop in pyqt5. While running, the mainwindow is not responding due to long loop.

What I want I want to have a STOP pushbutton to kill that loop. This button should still get active while the loop is running and when I press that it would stop the loop or kill the running.

My Code

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def print_this(self):

        to_loop = 10000000
        for n in range(to_loop):
            print(n)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(329, 205)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(70, 60, 75, 23))
        self.pushButton.setText('Start Loop')
        self.pushButton.clicked.connect(self.print_this)
        self.pushButton.show()

        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(170, 60, 75, 23))
        self.pushButton_2.setText('Stop')
        self.pushButton_2.show()

        MainWindow.setCentralWidget(self.centralwidget)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

My Attempt I believe it has something to do with multiprocessing, qthread, qprocess but I couldn't just integrate it with my code. Appreciate your help. Thank you!

P.S please respond in one .py solution as I have so much codes in my actual workings. Thank you!

Upvotes: 0

Views: 192

Answers (1)

jairoar
jairoar

Reputation: 247

You don't need to use QThreads at all, instead you need to use QProcess. You can kill the QProcess with your Stop button and start other QProcess with your Start Loop button, this allows you to use your GUI while your loop is running. I also added a print function if you need to see the output of your script.

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
#path of your for loop script
user_script = "insert your loop path"

class Ui_MainWindow(QtCore.QObject):
    
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(329, 205)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(70, 60, 75, 23))
        self.pushButton.setText('Start Loop')
        self.pushButton.clicked.connect(self.start_loop)
        self.pushButton.show()
        
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(170, 60, 75, 23))
        self.pushButton_2.setText('Stop')
        #stop loop when push button
        self.pushButton_2.clicked.connect(self.stop_loop)
        self.pushButton_2.show()

        MainWindow.setCentralWidget(self.centralwidget)
        
        #create process
        self.process = QtCore.QProcess()
        self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)

    def start_loop(self):

        self.process.start("python", ["-u", user_script])
        
    def stop_loop(self):
        self.process.kill()
        #this prints the output
        output = self.process.readAll()
        output = str(output.data(), encoding = "utf-8")
        print(output)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

And your "user_script" is a simple Python script with the following loop:

to_loop = 1000000
for n in range(to_loop):
    print(n) 

Upvotes: 1

Related Questions