5

I would like to provide the user of a plugin with progress status using messages and a progress bar.

My plugin processes several files using memory files, processing, writing to disk etc. It all works well, but takes 10 to 90 seconds run. In QGIS 2.18 it ran for about 5 seconds displaying progress text in the status bar, then the Windows wait icon displays and QGIS is unresponsive until complete - status bar hangs and QGIS looks frozen. In version 3.0, (the same plugin after updating the code), QGIS appears to freezes immediately (although the code is working properly), and status text does not display at all until after the routine has finished.

I am using Windows 10 and QGIS 3.4.2. My code takes long enough to require a status bar, but my attempts to display any information only occurs after the code has finished. I have looked into tasks and running code in the background, but there appear to be bugs yet to be resolved (QgsTask and task manager cause crash when used in function scope). Is there any way in QGIS 3.0 to show progress during the processing steps?

Update: I have had some success with a progress bar as a widget in the message bar. By adding self.iface.mainWindow().repaint() after setting the bar value (setValue) the bar will display properly. If the code takes more than 5 seconds the screen freezes and no updates to QGIS until the code has run. If I add time.sleep(0.1) before and after setting value and repainting, the status bar works properly.

Is it normal to have to repaint the screen every time the status bar is to increment? Is the only workaround to "jiggle" the screen with the sleep-timer so it won't freeze?

The above solution came from Unresponsive MessageBar in QGIS 3

2

1 Answer 1

6

I have created a minimal QGIS plugin to demonstrate the usage of the QProgressBar widget (see: https://github.com/zsiki/progress). The main point is to set the progress bar value regularly while data are processed.

  1. I've created a new plugin with PluginBuilder
  2. I've edited the dialog with Qt 5 Designer, a QProgressBar and a QPushButton were added dialog with progressbar and push button
  3. I've renamed the QPushButton to startButton and saved the dialog
  4. I've edited the progress_dialog.py and added a click even handler to the startButton in the __init__ function after setupUi

    self.startButton.clicked.connect(self.proc)

  5. I've added the proc to the end of progress_dialog.py. ProgressBar range is from 0 to 100 by default (unfortunately QProgressBar.Range, Minimum and Maximum not implemented in PyQt5 so you should scale your range to 0-100)

    def proc(self):
    self.progressBar.reset()
    for i in range(101):
        self.progressBar.setValue(i)
        # do something useful here instead of sleep
        time.sleep(0.2)
    
  6. Don't forget to import time for sleep but probably in your plugin sleep will be replaced by some useful code.

You may remove OK button and add a self.ok() call at the end of proc function to close the dialog after finishing.

See the whole code on GitHub: https://github.com/zsiki/progress

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.