2

I'm creating a legend in my print composer and only want "visible", or active, layers shown in the legend. This means I want only layers with the box checked in my layers panel.

Here is how I create my legend.

legend = QgsLayoutItemLegend(layout)
legend.setTitle("Legend")
layout.addLayoutItem(legend)

Looking at the documentation for QgsLayoutItemLegend there is a method: setLegendFilterByMapEnabled() whose description is: enter image description here

This leads me to believe if I do something like:

legend.setLegendFilterByMapEnabled(True)

My legend will only include "active" layers. But my legend still includes all layers, active and inactive.

What am I missing?

4

The method setLegendFilterByMapEnabled will filter legend items to those layers which are spatially located i.e. have features which are within the area shown in your layout map, it won't filter out layers which are not checked in your table of contents panel.


Correction: setLegendFilterByMapEnabled(True) filters the legend items to show just the ones visible in the associated layout map view. So, if a layer is not checked it will not be visible in the map view and therefore will not appear in the legend. Additionally, if no features of a layer or category thereof (e.g. for layers rendered with categorised/ graduated symbology) are visible in the associated layout map view, the legend node will be filtered out even if it is still checked in the main layers panel.

So, in retrospect, for most applications setLegendFilterByMapEnabled would probably do exactly what you want. You just have to call refresh() after setting it enabled:

legend.setLegendFilterByMapEnabled(True)
legend.refresh()

To add only layers checked in the layers panel to your legend, you need to do something like this:

#get checked layer tree layer objects and store their names in a list
checked_lyrs = [l.name() for l in QgsProject().instance().layerTreeRoot().children() if l.isVisible()]
#get map layer objects of checked layers by matching their names and store those in a list
lyrsToAdd = [l for l in QgsProject().instance().mapLayers().values() if l.name() in checked_lyrs]
legend = QgsLayoutItemLegend(layout)
legend.setTitle('Legend')
root = QgsLayerTree()
for lyr in lyrsToAdd:
    #add layer objects to the layer tree
    root.addLayer(lyr)
legend.model().setRootGroup(root)
layout.addItem(legend)
  • I completely misunderstood setLegendFilterByMapEnabled() so thank you for explaining that method. Also, this is amazing. You have really helped me out recently! Two questions I have: in your checked_lyrs list comprehension line, where did you get the .children() method from? I don't see it as a method in the QgsLayerTree class. I understand the children are the items in the Layer Tree. Or is this a generic method I can call on any object that contains multiple items? The same applies to: root.addLayer(lyr). Shouldn't .addLayer be a method of QgsLayerTree? – Erich Purpur Jan 31 at 15:44
  • Another question: in the legend.model().setRootGroup() line. .model is a method of QgsLayoutItemLegend class which "returns the legend model" (that isn't very descriptive). and .setRootGroup is a method of QgsLayerTreeModel class. How can these be chained together like that? Apologies for the questions but I'm just trying to understand as best I can. – Erich Purpur Jan 31 at 15:47
  • 1
    No problem @Erich Purpur. All your questions above which are causing your confusion are answered by class inheritance. I you look at the API Docs for a class (I find the C++ docs are actually more helpful for this), often you will see an inheritance diagram. Many classes inherit attributes and methods from other classes. So calling .children() on a QgsLayerTree object is possible because it is an inherited method from the QgsLayerTreeNode class. Likewise, addLayer() is an inherited method from QgsLayerTreeGroup and setRootGroup() is inherited from the QgsLayerTreeModel class – Ben W Feb 1 at 0:57
  • 1
    Link to C++ Docs: qgis.org/api/annotated.html Example of class inheritance diagram: qgis.org/api/classQgsLayerTree.html Also, if you scroll down the documentation you will often see the "Additional Inherited Members" for a class. – Ben W Feb 1 at 1:01
  • Great, thanks again. I've been looking only at the python documentation. I'll be sure to reference the c++ documentation in the future. – Erich Purpur Feb 1 at 13:06

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.