5

I have been trying to get one layer's clicked-on feature to have an effect on another layer's viewed features with some success, but I am unable to get the map canvas to be filled by the the selected layer's features when using python code called from within the layer actions call.

For reference, I have two layers - one not referred to in the code is a layer of zones. The other (referred to below) is the same zones intersected with same to identify all zones with their neighbouring zones. My intention is that on clicking on a zone in the former layer, I get the neighbouring zones highlighted, and zoomed to as a seamless operation.

When I run this code from the python console, it behaves exactly as I was hoping for:

registry = QgsMapLayerRegistry.instance();
name= 'intersecting_zones';
layer = registry.mapLayersByName( name )[0];
layer.removeSelection();
expr = QgsExpression("\"msoa_code_\"='E02002869'");
it = layer.getFeatures(QgsFeatureRequest(expr));
ids = [i.id() for i in it];
layer.setSelectedFeatures(ids);
box = layer.boundingBoxOfSelected();
iface.mapCanvas().setExtent(box);
iface.mapCanvas().refresh();

This will not work in the exact form within the python call of the original layer's action properties and I have understood that instead of using iface, I needed to switch to using a reference to QgsMapCanvas, hence I use code of the following form - first easy to read, second same code in the single line for use within Layer Actions.

from qgis.coreimport QgsApplication;
from qgis.gui import QgsMapCanvas;
registry = QgsMapLayerRegistry.instance();
canvas = QgsMapCanvas();
name= 'intersecting_zones';
layer = registry.mapLayersByName( name )[0];
layer.removeSelection();
expr = QgsExpression("\"msoa_code_\"='[% "msoa_code_" %]'");
it = layer.getFeatures(QgsFeatureRequest(expr));
ids = [i.id() for i in it];
layer.setSelectedFeatures(ids);
canvas.setExtent(layer.extent());
canvas.refresh();

from qgis.core import QgsApplication; from qgis.gui import QgsMapCanvas; registry = QgsMapLayerRegistry.instance(); canvas = QgsMapCanvas(); name= 'intersecting_zones'; layer = registry.mapLayersByName( name )[0]; layer.removeSelection(); expr = QgsExpression("\"msoa_code_\"='[% "msoa_code_" %]'"); it = layer.getFeatures(QgsFeatureRequest(expr)); ids = [i.id() for i in it]; layer.setSelectedFeatures(ids); canvas.setExtent(layer.extent()); canvas.refresh();

This code (from within Layer Actions) works to a point, I get no error message and the desired target features are selected. However, I cannot get the zoom to selected features functionality to work at all. Am I using the pyqgis code incorrectly, or is there some other approach I should be using to get this last bit working?

2 Answers 2

5

Try this code snippet to zoom to selected features of the layer:

canvas = qgis.utils.iface.mapCanvas()
canvas.zoomToSelected(layer) # zooms to selected feature extent for layer
3
  • is there any way to run qgis,utils.iface in headless mode (outside QGIS) ? Commented Apr 4, 2018 at 3:48
  • Yes, you need to create the app object then import the qgis module.
    – artwork21
    Commented Apr 4, 2018 at 12:47
  • But it return "NoneType".. so i got this error (NoneType object has no attribute mapCanvas) Commented May 22, 2018 at 3:16
2

Excellent - that works perfectly. Final code used is:

from qgis.coreimport QgsApplication;
from qgis.gui import QgsMapCanvas;
registry = QgsMapLayerRegistry.instance();
canvas = qgis.utils.iface.mapCanvas()
name= 'intersecting_zones';
layer = registry.mapLayersByName( name )[0];
layer.removeSelection();
expr = QgsExpression("\"msoa_code_\"='[% "msoa_code_" %]'");
it = layer.getFeatures(QgsFeatureRequest(expr));
ids = [i.id() for i in it];
layer.setSelectedFeatures(ids);
canvas.zoomToSelected(layer)
canvas.refresh();
0

Your Answer

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

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