PySide6 updating GUI text from a loop in a thread

176 views Asked by At

What I am trying to do is creating a separate thread from the GUI, and then in a loop, update the GUI text in every 0.01 second. I came up with the following code by searching the web, but it seems that the app gets stuck at the while loop. Isn't the count() supposed to run in another thread? What is wrong?

import sys
import time

from PySide6.QtCore import QSize, Qt, QThreadPool, Slot
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton

class MainWindow(QMainWindow):
    Count = 1;

    def __init__(self):
        super().__init__()

        self.setWindowTitle("My App")
        self.MyButton = QPushButton()
        self.setCentralWidget(self.MyButton)
        self.threadManager = QThreadPool();

    def showEvent(self, event):
        self.threadManager.start(self.count())

    def count(self):
        while(True):
            self.Count+=1;
            QMetaObject.invokeMethod(self, "refreshButtonText");
            time.sleep(0.01)

    @Slot()
    def refreshButtonText(self):
        self.MyButton.setText(f"Count {self.Count}")

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

PS: Updated the code above to be a working example, in case future people find this post when they search for a minimal example of updating the GUI in a long-running task in QT/PySide.

1

There are 1 answers

3
mugiseyebrows On BEST ANSWER

You accidentally called count instead of passing it as a function.

self.threadManager.start(self.count)

Instead of directly accessing objects in another thread consider using signal-slot mechanism to send data messages.

You can easily find out which thread something runs in by

print("I'm running in", QThread.currentThread())

Instead of thread you can just use timer

import sys

from PySide6.QtCore import QTimer
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton

class MainWindow(QMainWindow):
    Count = 1

    def __init__(self):
        super().__init__()
        self.setWindowTitle("My App")
        self.MyButton = QPushButton()
        self.setCentralWidget(self.MyButton)
        
    def showEvent(self, event):
        timer = QTimer(self)
        timer.timeout.connect(self.count)
        timer.start(10)

    def count(self):
        self.Count+=1
        self.refreshButtonText()

    def refreshButtonText(self):
        self.MyButton.setText(f"Count {self.Count}")

app = QApplication(sys.argv)

window = MainWindow()
window.show()

app.exec()