[GIS] Refreshing MapCanvas while PyQGIS-script is running

mapcanvaspyqgisqgis

I try to write a PyQGIS script similar to this:
Use of python console to prepare offline map from WMS (tile downloader).

Basically there are two loops to pan the mapCanvas, refresh the mapCanvas and export the mapCanvas to *.png.

iface.mapCanvas().setExtent(QgsRectangle(xmin, ymin, xmax, ymax))
time.sleep(5)
iface.mapCanvas().refresh()
time.sleep(5)
iface.mapCanvas().saveAsImage("D:/GE"+str(i)+"to"+str(j)+"img.png" )

If I execute this code line by line in the Python Console it is working fine. If I use it in a loop georeferenced png will be exported but they are either blank or contain all the same content. As you see above I tried to use time.sleep() to have a timeslot for the map to update. But was not successful.
As Joseph suggested I also tried:

for layer in qgis.utils.iface.mapCanvas().layers():
    layer.triggerRepaint()

Same problem here: works line by line in the Python Console but not in a loop.

How to refresh mapCanvas while PyQGIS-script is running?

(QGIS Version 2.14.3)

Best Answer

Sleep blocks the execution of your script for a while, synchronously.

One solution for your question is to use a QTimer, which controls when to execute functions and it's asynchronous, i.e., it allows other functions to continue to run (think of a map.refresh()) while waiting some milliseconds to run the next instruction.

Have a look at How to iterate over layers and export them as PNG images with PyQGIS in a standalone script for an implemented example that is similar to your case.

There are two functions, one to prepare the map (in your case, set the new extent and refresh the map) and another one to export the map. After the map is prepared, a QTimer is set to wait 1 second before calling exportMap(). Such second gives enough time for the map to reflect changes and be ready to be exported:

QTimer.singleShot(1000, exportMap)
Related Question