4. Toegang tot de inhoudsopgave (TOC)

Hint

De codesnippers op deze pagina hebben de volgende import nodig als u buiten de console van PyQGIS bent:

from qgis.core import (
    QgsProject,
    QgsVectorLayer,
)

U kunt verschillende klassen gebruiken om toegang te verkrijgen tot alle geladen lagen in de inhoudsopgave en ze gebruiken om informatie op te halen:

4.1. De klasse QgsProject

U kunt QgsProject gebruiken om informatie op te halen over de inhoudsopgave en alle geladen lagen.

U moet een instance van QgsProject maken en de methoden daarvan gebruiken om de geladen lagen op te halen.

De belangrijkste methode is mapLayers(). Het zal een woordenboek teruggeven van de geladen lagen:

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

De keys in het woordenboek zijn de unieke laag-ID’s, terwijl de values de gerelateerde objecten zijn.

Het is nu rechtdoorzee om alle andere informatie over de lagen op te halen:

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)>}

U kunt ook de inhoudsopgave bevragen met de naam van de laag:

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

Notitie

Een lijst met alle overeenkomende lagen wordt teruggegeven, dus maken we een index met [0] om de eerste laag met zijn naam op te halen.

4.2. klasse QgsLayerTreeGroup

De boom met lagen is een klassieke boomstructuur, gebouwd uit knopen. Er zijn momenteel twee groepen knopen: groepsknopen (QgsLayerTreeGroup) en laagknopen (QgsLayerTreeLayer).

Notitie

Voor meer informatie kunt u deze blogposts van Martin Dobias lezen: Part 1 Part 2 Part 3

Toegang tot de boom met lagen van het project kan gemakkelijk worden verkregen met de methode layerTreeRoot() van de klasse QgsProject:

root = QgsProject.instance().layerTreeRoot()

root is een groepsknoop en heeft children:

root.children()

Een lijst met directe kinderen wordt teruggegeven. Toegang tot kinderen van een subgroep zou moeten worden verkregen via hun eigen directe ouder.

We kunnen een van de kinderen ophalen:

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

Lagen kunnen ook worden opgehaald met hun (unieke) id:

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

En naar groepen kan ook worden gezocht met hun namen:

root.findGroup('Group Name')

QgsLayerTreeGroup heeft nog veel meer nuttige methoden die kunnen worden gebruikt om meer informatie op te halen over de inhoudsopgave:

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

Laten we nu enkele lagen toevoegen aan de boom met lagen van het project. Er zijn twee manieren om dat te doen:

  1. Expliciete toevoeging met de functies addLayer() of 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. Impliciete toevoeging: omdat de boom met lagen van het project is verbonden met het register van de lagen is het voldoende om een laag toe te voegen aan het register met kaartlagen:

    QgsProject.instance().addMapLayer(layer1)
    

U kunt gemakkelijk schakelen tussen QgsVectorLayer en QgsLayerTreeLayer:

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)>

Groepen kunnen worden toegevoegd met de methode addGroup(). In het voorbeeld hieronder, zal de eerste een groep toevoegen aan het einde van de inhoudsopgave, terwijl u met de laatste een andere groep kan toevoegen binnen een bestaande:

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

Er zijn vele nuttige methoden om knopen en groepen te verplaatsen.

Verplaatsen van een bestaande knoop wordt gedaan in drie stappen:

  1. klonen van de bestaande knoop

  2. verplaatsen van de gekloonde knoop naar de gewenste positie

  3. verwijderen van de originele knoop

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)

Het is iets meer gecompliceerder om een laag in de legenda te verplaatsen:

 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)

of om hem naar een bestaande groep te verplaatsen:

 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)

Enkele andere methoden die kunnen worden gebruikt om groepen en lagen aan te passen:

 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)