1

I have a PySide GUI in which several buttons trigger a long processing function, which subsequently updates GUI elements. Pushing the button freezes the GUI for a while until the processing completes. Since it takes a while, I wanted to add a progress bar. However, a QProgressBar does not show its progress updates until the main thread is idle, so simply calling progressBar.setValue() inside the processing loop doesn't work - the progressBar will just sit at 0 and then jump to 100% when the processing finishes.

I specifically DON'T want the entire GUI to remain responsive - there are a lot of elements which affect each other, and allowing the user to change anything while the processing is running can get things in an invalid state.


I have tried:

1) Using QProgressBar.update()

(How to show QProgressBar smoothly?).

Unfortunately this shows the progressBar updates for only about the first 5 seconds, but then the "Waiting" cursor shows up and the progressBar stops updating until the processing finishes.

2) Using QtGui.QApplication.processEvents()

(QProgressBar not showing progress?)

This shows the progress bar nicely for the full processing duration, but it keeps the rest of the GUI responsive - which in my case means the ability to queue multiple instances of the processing, potentially getting certain GUI elements "out of sync".


I have not yet tried moving the processing loop into a separate thread (also recommended by the link in #2) since I would expect that to have the same effect where it would be possible to get the GUI out of synq.


The brute-force solution would be to explicitly disable all the buttons and text edits that have the potential to get the GUI out of synq, and then reenable once the processing completes. But I'm hoping for a clean solution, something I can call inside the processing loop - instead of QtGui.QApplication.processEvents() - which will update the progressbar only, rather than the entire GUI.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Selvek
  • 130
  • 1
  • 9
  • Possible duplicate of [PyQt progress jumps to 100% after it starts](https://stackoverflow.com/questions/49647205/pyqt-progress-jumps-to-100-after-it-starts) – eyllanesc Jun 07 '19 at 21:55
  • The correct solution is to create a new thread, there to do the heavy lifting and send the progress information through a signal. processEvents only a monkey-patch, but this brings more problems than benefits, you can not limit the eventloop of Qt, and processEvents only causes all events (or a group of them) that have not yet been processed to be processed. – eyllanesc Jun 07 '19 at 21:58
  • The task of the painting itself is not heavy (it is optimized) so it is not advisable to use processEvents, the problem arises when there is a heavy task that blocks the eventloop, so the problem is the heavy task and the solution is to execute it in another thread . – eyllanesc Jun 07 '19 at 22:01
  • Use a second thread for the processing (as the others suggested) and put the progress bar in a modal dialog so the user can't touch the main window until the process ends.. – noEmbryo Jun 07 '19 at 23:40
  • I think the solution to this can be an external application that displays a Progress Bar. Your main app can open it with QProcess and send it the values to display through sockets or some other way. This way your main app doesn't need event loop, it will be run in external app. – Dmitriy Dec 09 '20 at 17:01

0 Answers0