Progress bar not showing up
-
I have a set of functions that when they run can take a few minutes to finish. I want to display a progress bar while they are running. I have a run function for now that just sleeps for x amount of time
def run(self, n): for i in range(n): time.sleep(.05) self.ui.progressBar.setValue(i+1)
and then in my main I have
def run_pls_gui(self): self.ui.progressBar = QProgressBar() n = 50 self.ui.progressBar.setMinimum(0) self.ui.progressBar.setMaximum(n) layout = QVBoxLayout() layout.addWidget(self.ui.progressBar) self.ui.pb_tester_connect_disconnect.clicked.connect(lambda: self.run(n))
eventually I am going to change this so that instead of calling 'self.run' I will call the functions that need to run. My question is, how do I get the progress bar to show up while this function runs? Do I need to add to run? Or add to my main?
-
You have 2 possibilities:
- The quick and dirty is adding QtCore.QCoreApplication.processEvents inside the loop of
run()
. - If you want to do it properly then move the computation to a different thread (e.g. with
QThread
orQtConcurrent
) and send update signals to the main thread to update the progress bar
- The quick and dirty is adding QtCore.QCoreApplication.processEvents inside the loop of
-
@poordev123 said in Progress bar not showing up:
So I would start a QThread in my main function and that would make the progress bar show up?
No, it's more involved than that, see https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
-
@poordev123 said in Progress bar not showing up:
So I would start a QThread in my main function and that would make the progress bar show up? From there I would then use
progressBar.setValue(x)
to do that?
Maybe it is a little easier to use
QtConcurrent::run()
instead of a fully fledged QThread. This is only an aside. There are several possibilities to use threads here.There is one thing all threaded solutions have in common: You cannot just call
progressBar.setValue(x)
. This function can only be called from the GUI thread. Otherwise your app might (occassionally) crash. Instead you have to put this call into the event loop of the GUI thread. Just have a signal inside your new thread connected to the slotsetValue()
of yourprogressBar
. Connections between threads will just work properly. You can also skip having your own slot and post an event inside the event loop of the GUI thread directly. In C++ this would look like this:QMetaObject::invokeMethod(qApp, [=](int x){ progressBar.setValue(x); });
One thing to remember: Don't update the progressBar too often as this will significantly slow down the actual computation. You can check if the progress value has actually changed (for one single percent) or if at least 100ms have passed (or both). This little trick can be the difference between seconds and minutes.