PyQt6: Use QTimer to run a loop for a few seconds before stopping

Viewed 134

I want to run a python while-loop for x amount of time (2 seconds) and then stop:

from PyQt6 import QtCore


def loop():
    stop = False

    def stop_loop():
        nonlocal stop
        stop = True
        print('STOPPING LOOP')

    timer = QtCore.QTimer()
    timer.setSingleShot(True)
    timer.setInterval(2000)
    timer.timeout.connect(stop_loop)
    timer.start()
    counter = 0
    while 1:
        counter += 1
        print(counter)
        if stop:
            break


app = QtCore.QCoreApplication([])
loop()
app.exec_()

But the loop keeps running infinitely and never stops.

1 Answers

The QTimer posts an event to the event-queue when it times-out, but your while-loop blocks all processing of events, so the timer-event never gets processed. To get your example to work, you would need to periodically force processing of any pending events:

def loop():
    ...
    while 1:
        counter += 1
        print(counter)
        # clear event-queue
        app.processEvents()
        if stop:
            break
        # do some more work...
        QtCore.QThread.msleep(100)

Whilst this method works for some simple cases, it's not usually very scalable, so the preferred approach is to move the blocking task into a separate worker thread, like this:

from PyQt6 import QtCore   

class Thread(QtCore.QThread):
    def stop(self):
        self._stopped = True
        print('STOPPING LOOP')

    def run(self):
        self._stopped = False
        counter = 0
        while not self._stopped:
            counter += 1
            print(counter)
            # do some more work...
            self.msleep(100)

app = QtCore.QCoreApplication(['Test'])

thread = Thread()
thread.finished.connect(app.quit)
QtCore.QTimer.singleShot(2000, thread.stop)
thread.start()

app.exec()
Related