3

I'm developing my QGIS3 plugin and I've realized that if I have the Python console active (so I can see it) the plugin behaves as expected, while if I don't see it doesn't. So this is the code:

for field in fields_db:
    field = field[0]
    layer = self.db.addPostGISLayer('fields', 'polygon', 'public',
                                    extra_name=field + '_',
                                    filter_text="field_name='{f}'".format(f=field))
    set_label(layer, 'field_name')
    QgsProject.instance().addMapLayer(layer)
    print('Added')
set_zoom(self.parent.iface, 1.1)
self.defined_field = ''

When I run the code with the python console present the layers adds one by one, and zoom to the fields. However when I don't have the Python console (or print('added') is comment away with a #). The code wait until all layers are ready to show and adds them at the same time in the end and it doesn't manage to zoom to the fields either(?). Any suggestions what I may edit?

This is the set_zoom code :

def set_zoom(iface, extra_extent):
    """
    Sets the zoom level to include all layers (excluding tiles layer) with some extra extent
    Parameters
    ----------
    iface: QGIS interface
        The QGIS iface module.
    extra_extent: float
        How much extra space around the layers eg. 1.1 is 10% extra
    Returns
    -------

    """
    zoom_extent = QgsRectangle()
    for layer in QgsProject.instance().mapLayers().values():
        if 'xyz&url' not in layer.source():
            zoom_extent.combineExtentWith(layer.extent())
    if zoom_extent.center().x() != 0.0:
        wgsCRS = QgsCoordinateReferenceSystem(4326)
        QgsProject.instance().setCrs(wgsCRS)
        zoom_extent.scale(extra_extent)
        iface.mapCanvas().setExtent(zoom_extent)
        iface.mapCanvas().refresh()
        wgsCRS = QgsCoordinateReferenceSystem(3857)
        QgsProject.instance().setCrs(wgsCRS)
4

It's a little quirk of running code in the Python console. In order for "print" statements to instantly show, it's necessary to run through the application's event loop once so that the Python console redraws and the print output is shown. But this loop execution allows other things to execute also -- such as the canvas responding to each newly added layer in turn.

When you run the whole code without the print statements, the rest of QGIS is "blocked" until your Python script completely finishes, and only THEN does it start processing the application event loop again. So in this case all the added layers will be responded to AT ONCE, after the script has completely finished.

In more recent QGIS versions the Python console no longer triggers this event loop on print statements, as it's often quite dangerous to execute the loop in the middle of other running code. As a result the print statements are deferred until the end of the Python script execution, and the behaviour should be the same with or without them included.

  • Thx Nyall for the clarification, I can confirm that the behaviour is same with/without console in 3.4.1. If there are no way to add the layers one by one, I'll probably rewrite the function to a qgstask so I can set a progressbar.. Any idea why calling of the set._zoom function doesn't work? – axel_ande Nov 12 '18 at 6:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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