4

I am working on a python plugin for QGIS using a layer containing linestrings, which I would like to have on top at all times. I have added the layer like the following:

QgsMapLayerRegistry.instance().addMapLayer(layer, addToLegend=False)

I don't want the layer to appear in the Layers Panel.

A similar question has been asked here without an accepted and for me meaningful answer.

According to Nathan W I can use the canvas method setLayerSet to set the render order on the canvas layers.

  • In case the current project already contains several layers, I need to know the current rendering order to correctly place my layer on top without disturbing the current order.

  • In case the user adds a new layer, how do I prevent the new layer from being ontop of mine? Is this handled by listening for some kind of a layer reordered signal on the canvas?

Question: What is the correct approach to handle this issue?


Update with solution notes:
I have implemented the answer provided by dmh126. To follow up on my questions I have determined that, it looks like canvas.layers() provide the layers in the order last given to the canvas.setLayerSet(...). Thus this list of layers can be used to include my layer on top directly:

layers = [my_layer] + canvas.layers()
canvas.setLayerSet([QgsMapCanvasLayer(x) for x in layers if x.id() != my_layer.id()])
# I don't want my layer in the list twice if it was already there due to a previous update.

The canvas signal layersChanged can be used to determine a change in the layers (new layer, removed layer, visibility change...), but remember to disconnect the listener when calling `canvas.setLayerSet(...)' because it will fire the signal again, probably causing a never ending call to the method called by the listener:

QObject.disconnect(canvas, SIGNAL('layersChanged()'), my_method)
layers = [my_layer] + canvas.layers()
canvas.setLayerSet([QgsMapCanvasLayer(x) for x in layers if x.id() != my_layer.id()])
QObject.connect(canvas, SIGNAL('layersChanged()'), my_method)

If I need to hide my layer, I can just remove it from the layer set like above:

layers = canvas.layers()
canvas.setLayerSet([QgsMapCanvasLayer(x) for x in layers if x.id() != my_layer.id()])
4

One way to do this:

  1. Create a function, that will set your layer on top (I guess there are a few solutions, you can use canvas.setLayerSet([top_layer, bottom_layer1, ...]) or something).
  2. Choose a signal from the list: http://qgis.org/api/classQgsMapCanvas.html It can be layersChanged() or something that occurs after you add a new layer or change hierarchy.
  3. Connect your function to that canvas signal.
  • How do I get the other layers so I can create the correct layer order with my layer on top? This is the issue I can't seem to get my head around. – Chau Dec 4 '15 at 16:41
  • canvas.layers() gives you a list of layers from the registry, now you can iterate over that list and set a proper order in new list for example. – dmh126 Dec 4 '15 at 16:45

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.