1

I'm working on QGIS 3.36. I'd like to show a background layer below other layers when I add layers.

I've been looking for a question about this issue in this forum, but the solutions I found work only for not temporary vector layers. The problem is that the line layers are placed below each other. How can I set a custom order for the visualization of these layers?

Here is the code:

canvas = QgsVectorLayer("Polygon?crs=epsg:3003", "canv", "memory")
cartesiano = QgsVectorLayer("LineString?crs=epsg:3003", "temp", "memory")
struttura = QgsVectorLayer("LineString?crs=epsg:3003", "grafico", "memory")
layerAnni = QgsVectorLayer('Point?crs=epsg:3003', 'puntiAnni', 'memory')

QgsProject.instance().addMapLayer(canvas)
QgsProject.instance().addMapLayer(cartesiano)
QgsProject.instance().addMapLayer(struttura)
QgsProject.instance().addMapLayer(layerAnni)

root = QgsProject.instance().layerTreeRoot()
for ch in root.children():
            
   if ch.name() == 'canv':
                
       root.insertChildNode(0, ch)
       root.removeChildNode(ch)

The layer I'd like to move to the bottom is "canv", but the if condition is not satisfied because the ch.name is "temp", the same as the other temporary layers added to this project.

1 Answer 1

0

I will preface this answer with the following:

When I run the first part of your code which creates and adds the temporary layers, they are added one above the other starting with canvas so that "canv" is at the bottom, then the line layers and finally the point layer on top which is already in the logical order.

The problem is that the line layers are placed below each other.

This problem statement does not make any sense to me.

but the if condition is not satisfied because the ch.name is "temp", the same as the other temporary layers added to this project.

I do not reproduce this described behavior.

However, here are some different options to reorder layer nodes in the layer tree view.

The simplest is instead of adding layers to the project one at a time, just use the addMapLayers() method and pass a list of layers you want to add in the desired order starting with index 0 on top:

canvas = QgsVectorLayer("Polygon?crs=epsg:3003", "canv", "memory")
cartesiano = QgsVectorLayer("LineString?crs=epsg:3003", "temp", "memory")
struttura = QgsVectorLayer("LineString?crs=epsg:3003", "grafico", "memory")
layerAnni = QgsVectorLayer('Point?crs=epsg:3003', 'puntiAnni', 'memory')

layer_order = [layerAnni, struttura, cartesiano, canvas]

QgsProject.instance().addMapLayers(layer_order)

Result:

enter image description here

You could also use the reorderGroupLayers() method which was added in QGIS 3.30:

canvas = QgsVectorLayer("Polygon?crs=epsg:3003", "canv", "memory")
cartesiano = QgsVectorLayer("LineString?crs=epsg:3003", "temp", "memory")
struttura = QgsVectorLayer("LineString?crs=epsg:3003", "grafico", "memory")
layerAnni = QgsVectorLayer('Point?crs=epsg:3003', 'puntiAnni', 'memory')

start_order = [struttura, canvas, layerAnni, cartesiano]

QgsProject.instance().addMapLayers(start_order)

new_order = [layerAnni, struttura, cartesiano, canvas]

root = QgsProject.instance().layerTreeRoot()

root.reorderGroupLayers(new_order)

Result:

enter image description here

Another option is, when adding layer/layers to the project via addMapLayer() or addMapLayers(), pass False as the second argument which will add the layers to the project but not the layer tree/legend, then you can insert the layers to the root group in the order you want:

canvas = QgsVectorLayer("Polygon?crs=epsg:3003", "canv", "memory")
cartesiano = QgsVectorLayer("LineString?crs=epsg:3003", "temp", "memory")
struttura = QgsVectorLayer("LineString?crs=epsg:3003", "grafico", "memory")
layerAnni = QgsVectorLayer('Point?crs=epsg:3003', 'puntiAnni', 'memory')

map_layers = [struttura, canvas, layerAnni, cartesiano]

QgsProject.instance().addMapLayers(map_layers, False)

root = QgsProject.instance().layerTreeRoot()

new_order = [layerAnni, struttura, cartesiano, canvas]

for i, lyr in enumerate(new_order):
    root.insertLayer(i, lyr)

Result:

enter image description here

Finally, if you want to want to create a new layer node and remove the old one, you need to clone the original node, otherwise QGIS will crash. See the docs for insertChildNode() which state that:

The node must not have a parent yet. The node will be owned by this group.

canvas = QgsVectorLayer("Polygon?crs=epsg:3003", "canv", "memory")
cartesiano = QgsVectorLayer("LineString?crs=epsg:3003", "temp", "memory")
struttura = QgsVectorLayer("LineString?crs=epsg:3003", "grafico", "memory")
layerAnni = QgsVectorLayer('Point?crs=epsg:3003', 'puntiAnni', 'memory')

start_order = [layerAnni, canvas, struttura, cartesiano]

QgsProject.instance().addMapLayers(start_order)

root = QgsProject.instance().layerTreeRoot()
for ch in root.children():
    print(ch)
    if ch.name() == 'canv':
       root.insertChildNode(len(root.children()), ch.clone())
       root.removeChildNode(ch)

Result:

enter image description here

4
  • I'm sorry, but these solutions don't work: the first doesn't put canv layer at the bottom, it put this layer at second position, above "struttura" and "cartesiano", the second same thing, the third "ch.name()" isn't 'canv', so the code doesn't enter into "if" condition Commented Nov 12 at 17:38
  • @SalvatoreDiolosà, I have updated my answer and added visual evidence in the form of screencasts of all of these options working. You can verify the code being run and view the result. I have tested these snippets on multiple machines and versions of QGIS. If these snippets are not working for you then there must be some other reason at play. Without more information I cannot help you further. I answered your question in good faith based on the information at hand.
    – Ben W
    Commented Nov 13 at 11:28
  • The code really is longer but I was focusing on this problem. I tried this your code in a new project and it works, but not in mine. The third solution, then, makes to crash Qgis. Commented Nov 13 at 17:06
  • I resolved. I re-added two layers in an other function connected to main. I'm sorry and thank you very much. Commented Nov 13 at 18:05

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.