0

I'm working with QGIS 3.40 (Bratislava) and I’m trying to automatically hide all layer names in a print-composer legend. Right now, I’m doing it manually: right-clicking each layer in the legend and selecting Hide, one by one. After that, I reorganize the layers inside a group to get the adaptive legend I want.

Since I’m generating an atlas and need to repeat this process very often, I’d like to automate it with PyQGIS.

I found a related topic here and I used a slightly different code: Setting layer name in composer legend as "Hidden" using PyQGIS?

from qgis.core import ( QgsProject, QgsLayoutItemLegend, QgsLegendRenderer, QgsLegendStyle, QgsLayerTreeNode ) # ------------------------------------------------------------------ # Fonction récursive : masque un nœud et tous ses nœuds descendants # ------------------------------------------------------------------ def hide_node_recursively(node): # Masquer le nœud lui-même QgsLegendRenderer.setNodeLegendStyle(node, QgsLegendStyle.Hidden) # Parcourir les enfants s'il y en a if hasattr(node, "children"): for child in node.children(): hide_node_recursively(child) # ------------------------------------------------------------------ # 1. Récupération du layout # ------------------------------------------------------------------ project = QgsProject.instance() manager = project.layoutManager() layout = manager.layoutByName('atlas') # Adapter si nécessaire if layout is None: raise Exception("Layout 'atlas' not found.") # ------------------------------------------------------------------ # 2. Récupération de la légende # ------------------------------------------------------------------ legends = [i for i in layout.items() if isinstance(i, QgsLayoutItemLegend)] if not legends: raise Exception("No legend found in layout.") legend = legends[0] # ------------------------------------------------------------------ # 3. Désactivation des mises à jour automatiques # ------------------------------------------------------------------ legend.setAutoUpdateModel(False) legend.updateLegend() # ------------------------------------------------------------------ # 4. Masquage récursif de TOUTE la légende # ------------------------------------------------------------------ model = legend.model() root = model.rootGroup() hide_node_recursively(root) # <-- récursion totale # ------------------------------------------------------------------ # 5. Rafraîchir la légende et le layout # ------------------------------------------------------------------ legend.refresh() layout.refresh() 

But it's interfering with the code I use to remove the "bande 1" in the print-composer with a code that was given to me on the forum (thanks again it's working well alone!) here : Automate the turn off QGIS band number in the legend

layout_name = "atlas" #Adjust to match the name of your layout #Find the layout object by its name lm = QgsProject.instance().layoutManager().layoutByName(layout_name) #List legends, pick the first (0) one. legend = [x for x in lm.items() if isinstance(x, QgsLayoutItemLegend)][0] #For each child in the legend, if it is a Legend Node, # change its label to a whitespace model = legend.model() children = list(model.children()) for child in children: if isinstance(child, QgsSimpleLegendNode): #print(child) #<QgsSimpleLegendNode: "Band 1: Layer_1 (Palette)"> #<QgsSimpleLegendNode: "Band 1 (Gray)"> child.setUserLabel(" ") 

Do you have an idea to them make both work together ?

Thanks a lot for your help!

1 Answer 1

0

Found a solution thaks to the AI Claude, I post it here if it can help somebody later :

from qgis.core import ( QgsProject, QgsLayoutItemLegend, QgsLegendRenderer, QgsLegendStyle, QgsLayerTreeNode, QgsLayerTreeLayer, QgsLayerTreeGroup, QgsMapLayerLegendUtils ) # ------------------------------------------------------------------ # Fonction pour trouver un groupe par nom # ------------------------------------------------------------------ def find_group_by_name(root, group_name): """ Recherche récursivement un groupe par son nom dans l'arbre des couches """ if isinstance(root, QgsLayerTreeGroup): if root.name() == group_name: return root for child in root.children(): result = find_group_by_name(child, group_name) if result: return result return None # ------------------------------------------------------------------ # Fonction récursive : cache les noms des nœuds # ------------------------------------------------------------------ def process_legend_tree(node, legend_model): """ Parcourt l'arbre de légende et cache tous les noms """ # Cache le style du nœud (groupe ou couche) if isinstance(node, (QgsLayerTreeGroup, QgsLayerTreeLayer)): QgsLegendRenderer.setNodeLegendStyle(node, QgsLegendStyle.Hidden) print(f"Caché nœud: {node.name()}") # Si c'est une couche, traiter ses symboles/bandes if isinstance(node, QgsLayerTreeLayer): layer = node.layer() if layer: # Essayer de désactiver complètement la légende de la couche try: QgsMapLayerLegendUtils.setLegendNodeUserLabel(node, 0, "\u200B") except: pass # Récupérer les nœuds de légende legend_nodes = legend_model.layerLegendNodes(node) if legend_nodes: print(f" -> {len(legend_nodes)} nœud(s) de légende") for i, legend_node in enumerate(legend_nodes): try: current_label = legend_node.data(0) print(f" Nœud {i}: '{current_label}'") # Cacher le nœud de légende avec caractère invisible legend_node.setUserLabel("\u200B") try: legend_node.setUserPatchSize(0, 0) except: pass print(f" -> Traité") except Exception as e: print(f" Erreur: {e}") # Parcourir récursivement les enfants if isinstance(node, QgsLayerTreeGroup): for child in node.children(): process_legend_tree(child, legend_model) # ------------------------------------------------------------------ # Fonction pour collecter toutes les couches d'un groupe # ------------------------------------------------------------------ def collect_layers_from_group(group): """ Collecte récursivement toutes les couches d'un groupe """ layers = [] for child in group.children(): if isinstance(child, QgsLayerTreeLayer): layers.append(child.layer()) elif isinstance(child, QgsLayerTreeGroup): layers.extend(collect_layers_from_group(child)) return layers # ------------------------------------------------------------------ # SCRIPT PRINCIPAL # ------------------------------------------------------------------ project = QgsProject.instance() manager = project.layoutManager() layout_name = 'atlas' group_name = 'atlas' # Nom du dossier/groupe dans le panneau des couches print(f"=== Recherche du layout '{layout_name}' ===") layout = manager.layoutByName(layout_name) if layout is None: raise Exception(f"Layout '{layout_name}' non trouvé.") # Récupération de la légende legends = [i for i in layout.items() if isinstance(i, QgsLayoutItemLegend)] if not legends: raise Exception("Aucune légende trouvée dans le layout.") legend = legends[0] print(f"Légende trouvée\n") # ------------------------------------------------------------------ # ÉTAPE 1 : RÉINITIALISER LA LÉGENDE # ------------------------------------------------------------------ print(f"=== ÉTAPE 1 : Réinitialisation de la légende ===") # Réactiver les mises à jour automatiques temporairement legend.setAutoUpdateModel(True) print("Mises à jour automatiques activées") # Mettre à jour depuis le projet legend.updateLegend() print("Légende mise à jour depuis le projet") # Désactiver à nouveau les mises à jour automatiques legend.setAutoUpdateModel(False) print("Mises à jour automatiques désactivées\n") # ------------------------------------------------------------------ # ÉTAPE 2 : RÉCUPÉRER LES COUCHES DU GROUPE "ATLAS" # ------------------------------------------------------------------ print(f"=== ÉTAPE 2 : Récupération des couches du groupe '{group_name}' ===") # Trouver le groupe "atlas" dans le panneau des couches root_project = project.layerTreeRoot() atlas_group = find_group_by_name(root_project, group_name) if atlas_group is None: print(f"ATTENTION : Le groupe '{group_name}' n'a pas été trouvé dans le panneau des couches.") print("La légende utilisera toutes les couches du projet.") else: print(f"Groupe '{group_name}' trouvé") # Collecter toutes les couches du groupe atlas_layers = collect_layers_from_group(atlas_group) print(f"{len(atlas_layers)} couche(s) trouvée(s) dans le groupe '{group_name}':") for layer in atlas_layers: print(f" - {layer.name()}") # Filtrer la légende pour n'afficher que ces couches model = legend.model() legend_root = model.rootGroup() # Supprimer tous les éléments existants print("\nSuppression des éléments existants de la légende...") legend_root.removeAllChildren() # Ajouter les couches du groupe atlas print(f"Ajout des couches du groupe '{group_name}' à la légende...") for layer in atlas_layers: model.rootGroup().addLayer(layer) print(f" + {layer.name()}") print() # ------------------------------------------------------------------ # ÉTAPE 3 : MASQUER LES NOMS DES COUCHES ET BANDES # ------------------------------------------------------------------ print("=== ÉTAPE 3 : Masquage des noms de couches et bandes ===") model = legend.model() root = model.rootGroup() process_legend_tree(root, model) # ------------------------------------------------------------------ # ÉTAPE 4 : CONFIGURATION ADDITIONNELLE # ------------------------------------------------------------------ print("\n=== ÉTAPE 4 : Configuration additionnelle ===") try: legend.setStyleFont(QgsLegendStyle.Subgroup, legend.styleFont(QgsLegendStyle.SymbolLabel)) print("Style de police configuré") except: pass # ------------------------------------------------------------------ # ÉTAPE 5 : RAFRAÎCHISSEMENT FINAL # ------------------------------------------------------------------ print("\n=== ÉTAPE 5 : Rafraîchissement ===") legend.updateLegend() legend.adjustBoxSize() legend.refresh() layout.refresh() print("\n✓ Traitement terminé avec succès!") print("\nRésumé:") print("1. Légende réinitialisée") print(f"2. Couches du groupe '{group_name}' ajoutées") print("3. Noms des couches et bandes cachés") 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.