Updating progressbar from QRunner

Nice! But I would like to in progress_fn() method update self.progressbar widget form MainWindow! How to deal with: QObject::setParent: Cannot set parent, new parent is in a different thread.

Hey @Michal_Plichta it’s difficult to be sure without seeing the code, but the error sounds like you’re attempting to create the progressbar from in your thread? You can’t do this – all your widgets need to be on the main GUI thread, and stay there.

The approach to use is to create a persistent progressbar on your main window status bar (or anywhere else) and then emit only the progress from the runner. This should be emitted as a simple number – e.g. a int between 0 and 100, or a float between 0 and 1.

Here is a minimal working example

from PyQt5.QtWidgets import (
    QWidget, QApplication, QProgressBar, QMainWindow
)

from PyQt5.QtCore import (
    Qt, QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool
)
import time


class WorkerSignals(QObject):

    progress = pyqtSignal(int)
    


class JobRunner(QRunnable):
    
    signals = WorkerSignals()
    
    def __init__(self):
        super().__init__()
        
    @pyqtSlot()
    def run(self):
        for n in range(100):
            self.signals.progress.emit(n + 1)
            time.sleep(0.1)



class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        
        # Create a statusbar.
        self.status = self.statusBar()
        self.progress = QProgressBar()
        self.status.addPermanentWidget(self.progress)
        
        # Thread runner
        self.threadpool = QThreadPool()
        
        # Create a runner
        self.runner = JobRunner()
        self.runner.signals.progress.connect(self.update_progress)
        self.threadpool.start(self.runner)
        
        self.show()
    
    def update_progress(self, n):
        self.progress.setValue(n)
        
app = QApplication([])
w = MainWindow()
app.exec_()

When you run this you’ll see a window pop up, with a progress bar moving along from 0 to 100 (increasing by 1 every 1/10 of a second). The updates are coming as int values from the single JobRunner object we create and add to the threadpool in the window init.

progress

1 Like

@Michal_Plichta

Great and very good question useful for a lot of people. :smile:

By PM I have asked to Martin for making a tutorial about progressBar and even more.
I’m going to search this one and open a PR.

@martin

You have this ability (which I don’t have ) to simply explain complicated things so that we can understand them from the beginning.