4. Accediendo a la Tabla de Contenidos (TOC)

Consejo

Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de pyqgis:

from qgis.core import (
    QgsProject,
    QgsVectorLayer,
)

Puede usar diferentes clases para acceder a todas las capas cargadas en la TOC y usarlas para obtener información:

4.1. La clase QgsProject

Puede usar la clase QgsProject para recuperar información sobre la TOC y todas las capas cargadas.

Debe crear una instance de QgsProject y usar sus métodos para obtener las capas cargadas.

El método principal es mapLayers(). Devolverá un diccionario con las capas cargadas:

layers = QgsProject.instance().mapLayers()
print(layers)
{'countries_89ae1b0f_f41b_4f42_bca4_caf55ddbe4b6': <QgsVectorLayer: 'countries' (ogr)>}

Las claves del diccionario son las ids únicas de capa mientras que los valores son los objetos relacionados.

Ahora es sencillo obtener cualquier otra información sobre las capas:

1# list of layer names using list comprehension
2l = [layer.name() for layer in QgsProject.instance().mapLayers().values()]
3# dictionary with key = layer name and value = layer object
4layers_list = {}
5for l in QgsProject.instance().mapLayers().values():
6  layers_list[l.name()] = l
7
8print(layers_list)
{'countries': <QgsVectorLayer: 'countries' (ogr)>}

Puede además consultar la TOC usando el nombre de la capa:

country_layer = QgsProject.instance().mapLayersByName("countries")[0]

Nota

Se devuelve una lista con todas las capas coincidentes, por lo que indexamos con [0] para obtener la primera capa con este nombre.

4.2. Clase QgsLayerTreeGroup

La capa árbol es una estructura clásica de árbol construida con nodos. Hay actualmente dos tipos de nodos: nodos de grupo (QgsLayerTreeGroup) y nodos de capa (QgsLayerTreeLayer).

Nota

para mas información puede leer este blog puesto por Martin Dobias: Part 1 Part 2 Part 3

Se puede acceder fácilmente al árbol de capas del proyecto con el método layerTreeRoot() de la clase QgsProject:

root = QgsProject.instance().layerTreeRoot()

root es un nodo de grupo y tiene hijos:

root.children()

Se devuelve una lista de hijos directos. Se debe acceder a los hijos del subgrupo desde su propio padre directo.

Podemos recuperar uno de los hijos:

child0 = root.children()[0]
print(child0)
<QgsLayerTreeLayer: countries>

Las capas también se pueden recuperar usando su (única) id:

ids = root.findLayerIds()
# access the first layer of the ids list
root.findLayer(ids[0])

Y los grupos también se pueden buscar usando sus nombres:

root.findGroup('Group Name')

QgsLayerTreeGroup tiene muchos otros métodos útiles que se pueden utilizar para obtener más información sobre el TOC:

# list of all the checked layers in the TOC
checked_layers = root.checkedLayers()
print(checked_layers)
[<QgsVectorLayer: 'countries' (ogr)>]

Ahora agreguemos algunas capas al árbol de capas del proyecto. Hay dos formas de hacerlo:

  1. Adición explícita usando las funciones addLayer() o insertLayer():

    1# create a temporary layer
    2layer1 = QgsVectorLayer("path_to_layer", "Layer 1", "memory")
    3# add the layer to the legend, last position
    4root.addLayer(layer1)
    5# add the layer at given position
    6root.insertLayer(5, layer1)
    
  2. Adición implícita: dado que el árbol de capas del proyecto está conectado al registro de capas, basta con agregar una capa al registro de capas del mapa:

    QgsProject.instance().addMapLayer(layer1)
    

Puede conmutar entre QgsVectorLayer y QgsLayerTreeLayer fácilmente:

node_layer = root.findLayer(country_layer.id())
print("Layer node:", node_layer)
print("Map layer:", node_layer.layer())
Layer node: <QgsLayerTreeLayer: countries>
Map layer: <QgsVectorLayer: 'countries' (ogr)>

Los grupos pueden ser añadidos con el método addGroup(). En el siguiente ejemplo, el primero agregará un grupo al final de la tabla de contenido, mientras que para el segundo puede agregar otro grupo dentro de uno existente:

node_group1 = root.addGroup('Simple Group')
# add a sub-group to Simple Group
node_subgroup1 = node_group1.addGroup("I'm a sub group")

Para mover nodos y grupos hay muchos métodos útiles.

Mover un nodo existente se hace en tres pasos:

  1. Clonando el nodo existente

  2. moviendo el nodo clonado a la posición deseada

  3. borrando el nodo original

1# clone the group
2cloned_group1 = node_group1.clone()
3# move the node (along with sub-groups and layers) to the top
4root.insertChildNode(0, cloned_group1)
5# remove the original node
6root.removeChildNode(node_group1)

Es un poco mas complicado mover una capa por la leyenda:

 1# get a QgsVectorLayer
 2vl = QgsProject.instance().mapLayersByName("countries")[0]
 3# create a QgsLayerTreeLayer object from vl by its id
 4myvl = root.findLayer(vl.id())
 5# clone the myvl QgsLayerTreeLayer object
 6myvlclone = myvl.clone()
 7# get the parent. If None (layer is not in group) returns ''
 8parent = myvl.parent()
 9# move the cloned layer to the top (0)
10parent.insertChildNode(0, myvlclone)
11# remove the original myvl
12root.removeChildNode(myvl)

o moverla a un grupo existente:

 1# get a QgsVectorLayer
 2vl = QgsProject.instance().mapLayersByName("countries")[0]
 3# create a QgsLayerTreeLayer object from vl by its id
 4myvl = root.findLayer(vl.id())
 5# clone the myvl QgsLayerTreeLayer object
 6myvlclone = myvl.clone()
 7# create a new group
 8group1 = root.addGroup("Group1")
 9# get the parent. If None (layer is not in group) returns ''
10parent = myvl.parent()
11# move the cloned layer to the top (0)
12group1.insertChildNode(0, myvlclone)
13# remove the QgsLayerTreeLayer from its parent
14parent.removeChildNode(myvl)

Algunos otros métodos que se pueden utilizar para modificar los grupos y capas:

 1node_group1 = root.findGroup("Group1")
 2# change the name of the group
 3node_group1.setName("Group X")
 4node_layer2 = root.findLayer(country_layer.id())
 5# change the name of the layer
 6node_layer2.setName("Layer X")
 7# change the visibility of a layer
 8node_group1.setItemVisibilityChecked(True)
 9node_layer2.setItemVisibilityChecked(False)
10# expand/collapse the group view
11node_group1.setExpanded(True)
12node_group1.setExpanded(False)