Search code examples
pythonmultithreadingpyqtpyqt5qthread

QThread does not update view with events


On menu I can trigger:

def on_git_update(self):
    update_widget = UpdateView()
    self.gui.setCentralWidget(update_widget)
    updateGit = UpdateGit()
    updateGit.progress.connect(update_widget.on_progress)
    updateGit.start()

then I have:

class UpdateView(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        vbox = QVBoxLayout()
        self.pbar = QProgressBar()
        vbox.addWidget(self.pbar)
        vbox.addStretch(1)
        self.setLayout(vbox)

    def on_progress(self, value):
        self.pbar.setValue(int(value * 100))


class UpdateGit(QThread):
    progress = pyqtSignal(float)

    def __del__(self):
        self.wait()

    def run(self):
        for i in range(10):
            self.progress.emit(i / 10)
            sleep(.5)

The app freezes during the processing, afaik it should work as it is in a thread using signals. Also, it works as expected with the app updating every step when I run it in debug mode via pycharm. How is my thread set up incorrectly?


Solution

  • A variable created in a function only exists until the function exists, and this is what happens with updateGit, in the case of update_widget when it is set as centralwidget it has a greater scope since Qt handles it. The solution is to extend the scope of the thread by making it a member of the class.

    def on_git_update(self):
        update_widget = UpdateView()
        self.gui.setCentralWidget(update_widget)
        self.updateGit = UpdateGit()
        self.updateGit.progress.connect(update_widget.on_progress)
        self.updateGit.start()