11

Im having a problem toggling the visibility of map layers in PyQGIS (2.4). I have a simple interface, just the map canvas, no legend, and a radio button that toggles between two raster layers.

Layers are initialized like this:

lyr = QgsRasterLayer(os.getcwd() + '/data/rasters/dof/dof.vrt', 'Ortophoto')
QgsMapLayerRegistry.instance().addMapLayer(lyr, False)
ml = QgsMapCanvasLayer(lyr)
ml.setVisible(False)

lyr2 = QgsRasterLayer(os.getcwd() + '/data/rasters/chm/chm.vrt', 'Chm')
QgsMapLayerRegistry.instance().addMapLayer(lyr2, False) ml2 = QgsMapCanvasLayer(lyr2) ml2.setVisible(True)

When I want to toggle their visibility I do:

ml.setVisible(True)
ml2.setVisible(False)

But unfortunately, the rendering on the map canvas stays the same.

What am I missing?

Taras
  • 32,823
  • 4
  • 66
  • 137
U2ros
  • 5,117
  • 5
  • 29
  • 51

3 Answers3

17

For QGIS 3, you have to use:

QgsProject.instance().layerTreeRoot().findLayer(layer_id).setItemVisibilityChecked(False)

or to be safe

node = QgsProject.instance().layerTreeRoot().findLayer(layer_id)
if node:
  node.setItemVisibilityChecked(False)

Reading the documentation, findLayer accepts both the layer itself and the layer ID as a string.

Taras
  • 32,823
  • 4
  • 66
  • 137
Denis Rouzaud
  • 1,618
  • 11
  • 16
4

At the moment (QGIS 2.x) (and I know it's a bit gross) but you also have to update the layer set on the canvas to update the layer state change

canvas.setLayerSet([ml2, ml])

This will also control the render order. m1 will reneder first then ml2 on top of it.

Denis Rouzaud
  • 1,618
  • 11
  • 16
Nathan W
  • 34,706
  • 5
  • 97
  • 148
1

In QGIS 2, You have to refresh the mapCanvas as well:

 ml.setVisible(True)
 ml2.setVisible(False)

 qgis.utils.iface.mapCanvas().refresh()

After this the map Canvas will redraw and you can see the changes.

Normally you should see changes when you zoom in and out to force a refresh of the mapCanvas manually.

To set the layer visibility you can use this:

 qgis.utils.iface.legendInterface().setLayerVisible(m1, False)
 qgis.utils.iface.legendInterface().setLayerVisible(m12, True)

I think mapCanvas doesn't have a method to set teh layer visibility. A setLayerVisibility can only be found in the QgsLegendInterface:

http://qgis.org/api/classQgsLegendInterface.html#ae77bf61a8c81bee9f861c6f7d7c7d8cf

If this doesn't work you can also change the transparency of a raster layer with QgsRasterTransparency.TransparentSingleValuePixel() like in this post

How do I set layer transparency in QGIS 2.0 with Python?

Denis Rouzaud
  • 1,618
  • 11
  • 16
Martin
  • 2,908
  • 4
  • 22
  • 44
  • Doesn't work.I tried zooming in/out anyway. – U2ros Oct 22 '14 at 12:02
  • I refreshed the map canvas instance directly self.ui.map.refresh() – U2ros Oct 22 '14 at 12:03
  • 1
    Must be something else in my code then. It is a helpful if i know this is the way to do it ;> – U2ros Oct 22 '14 at 12:04
  • Thanks for updating your answer... in 2.4 qgis.utils no longer exists. How do you access iface.legenInterface()? – U2ros Oct 22 '14 at 12:44
  • I use Qgis2.4 and i use for example to get the active layer in a plugin layer = qgis.utils.iface.activeLayer() or import qgis.utils – Martin Oct 22 '14 at 12:52
  • hmm, im using the api as a standalone application setup, import qgis.utils evaluates and the program exits. – U2ros Oct 22 '14 at 13:10