J'ai quelques couches avec des symboles définis par les données très complexes. Si j'utilise une légende dans le compositeur d'impression, ces symboles ne sont pas dessinés correctement.
Existe-t-il un moyen de modifier les symboles de légende avec des pyqgis, donc je peux utiliser des images PNG ou SVG personnalisées au lieu du symbole de légende par défaut pour ces couches?
Je sais comment ajouter un bouton-poussoir au composeur d'impression et comment le connecter à une fonction. Je veux ajouter un bouton aux paramètres de légende pour me permettre de remplacer l'icône de légende générée automatiquement par une image personnalisée. Donc, ce dont j'ai encore besoin, c'est de savoir comment accéder aux symboles de légende avec pyqgis / pyqt, et comment les remplacer par un QImage sur un QLabel ou quelque chose comme ça?
Maquette très basique du bouton utilisé pour changer le symbole:
Légende générée automatiquement:
Légende avec symbole de légende personnalisé:
J'ai déjà découvert comment accéder aux éléments de la légende dans le compositeur d'impression mais pas encore comment accéder au symbole lui-même:
import qgis
from PyQt4.QtCore import *
from PyQt4.QtGui import *
activeComposer = iface.activeComposers()
for item in activeComposer:
if item.composerWindow().windowTitle()=='test':
for i in item.items():
if isinstance(i,QgsComposerLegend):
#print i
#print i.model()
legend = i
for i in xrange(legend.modelV2().rowCount()):
posteleg=legend.modelV2().index(i, 0)
print posteleg.data()
Modifier 1:
J'ai également découvert comment accéder aux objets QIcon de l'arbre de légende, mais je ne peux pas encore les échanger:
def run(self):
activeComposer = self.iface.activeComposers()
#print(self.resolve('icon.png'))
for item in activeComposer:
if item.composerWindow().windowTitle()=='test':
for i in item.items():
if isinstance(i,QgsComposerLegend):
legend = i
layerIcon = QIcon(os.path.join(os.path.dirname(__file__), "icon.png"))
for i in xrange(legend.modelV2().rowCount()):
posteleg=legend.modelV2().index(i, 0)
posteleg.model().iconGroup().swap(layerIcon)
print posteleg.data()
Voici un exemple réel où vous pouvez voir une symbologie combinée de plusieurs couches de symboles: Cela se retrouvera dans la légende comme ceci:
Comme j'ai besoin du bon symbole dans la légende, je voudrais faire une capture d'écran de mon symbole, le recadrer et l'utiliser comme image dans ma légende.
Je sais que je pourrais simplement superposer une image distincte au-dessus de ma légende qui couvre le symbole généré automatiquement, mais j'aimerais avoir une solution "plus propre" qui me permette de remplacer les symboles de la légende par des images personnalisées.
Modifier 2:
En attendant, j'ai trouvé un autre moyen d'accéder aux entrées de la légende:
from qgis.core import QgsLegendRenderer, QgsComposerLegendStyle
compDict = {}
for comp in iface.activeComposers():
# workaround to get name: read it from window title
compDict[comp.composerWindow().windowTitle()] = comp.composition()
if "mycomposername" in compDict:
itemLlegend = compDict["mycomposername"].getComposerItemById("mylegend_id")
if itemLlegend:
print itemLlegend
tree_layer_layer = itemLlegend.modelV2().rootGroup().children()
for item in tree_layer_layer:
if item.layerName()=="MyLayername":
print "match"
QgsLegendRenderer.setNodeLegendStyle(item, QgsComposerLegendStyle.Group)
Cela me permet d'accéder aux objets QgsLayerTreeLayer et je peux changer le style de légende (Group, Subgroup, Hidden). Mais je ne sais toujours pas comment accéder au symbole de légende. Des idées?
Réponses:
Étant donné que ce sujet couvre de nombreux arguments, je ne me concentrerai que sur les couches de symboles SVG, en espérant avoir bien compris ce que vous recherchez (je n'ai pas réalisé la longueur de la réponse lors de l'écriture, donc je suis désolé pour mais j'espère que cela ajoutera plus de clarté).
Le contexte
1) Classes de couches de symboles
Les classes de couches de symboles suivantes sont disponibles pour le format SVG:
Une approche courante pour créer une couche de symboles consiste à l'initialiser avec un dictionnaire de propriétés.
Vous pouvez initialiser une nouvelle couche de symboles et voir ses propriétés par défaut de cette façon:
Vous obtiendrez toutes les propriétés qui y sont stockées:
Si vous souhaitez modifier les propriétés, vous pouvez utiliser des méthodes, qui peuvent être appelées à l'aide de la classe (par exemple exécutées
help(QgsSvgMarkerSymbolLayerV2)
dans la console Python). Vous verrez plus tard un exemple d'utilisation des méthodes.Par souci d'exhaustivité, vous pouvez également initialiser une couche de symboles avec un dictionnaire de propriétés (par exemple, voir ici ), mais je préfère sincèrement la première approche et je vais l'utiliser.
2) Création d'un rendu
Pour utiliser la couche de symboles une fois que vous l'avez créée (et éventuellement modifiée), vous devez créer un rendu approprié, puis affecter ce rendu à votre couche de carte.
Pour accéder au rendu existant d'un calque:
Pour obtenir une liste des types de rendu disponibles, utilisez:
Pour votre cas, nous devons traiter avec un rendu de symbole catégorisé . Comme je l'ai déjà dit, vous devez créer un moteur de rendu, puis l'assigner au calque:
3) Changer la couche de symboles
Les différents symboles du moteur de rendu de symboles catégorisé sont appelables via
symbols()
(il renvoie une liste):Si vous voulez remplacer une couche de symboles donnée dans la
symbol
définition précédente, il vous suffit de connaître son index et de le dire au rendu de cette manière:où
[0]
indique le premier élément du groupe catégorisé.Solution
Enfin, appliquons ce que nous venons d'apprendre!
En supposant de travailler sur cette couche de polygones, qui stocke les utilisations du sol que nous avons définies auparavant:
Si vous souhaitez modifier le modèle par défaut pour les utilisations des terres agricoles (ils ont la position n ° 1 dans le groupe 'landuse') avec une image SVG spécifique, vous pouvez exécuter ce code (lisez ici pour savoir comment ajouter un SVG personnalisé chemin):
Ce sera le résultat:
Le code ci-dessus est très approximatif mais, comme je ne savais pas si vous vouliez une solution spécifique pour votre exemple ou une explication plus générale, j'ai préféré concentrer l'attention sur les outils disponibles au lieu d'affiner le code lui-même (je suis sûr vous pouvez le modifier légèrement selon vos besoins spécifiques!).
la source
Alternativement, et sans codage Python, j'ai résolu cela en créant un nouveau groupe de calques dédié à la création de légendes, où je peux mettre tout ce que j'aime, avec les tailles et les couleurs que je veux. Comme ceci dans le compositeur d'impression, je viens de supprimer des éléments de légende les couches de données réelles et de ne conserver que le groupe de couches de légende.
Il est particulièrement pratique lorsque vous avez besoin de créer une légende qui peut représenter des cas qui ne se produisent pas sur la carte imprimée réelle.
EDIT: et à propos de votre deuxième édition, avec les symboles composés qui ne s'affichent pas correctement, avez-vous des variables définissant vos symboles, comme le "C" ou "G" est en fait relatif à un champ, ou l'orientation? Si c'est le cas, QGIS ne peut pas deviner ce que vous voulez afficher, il passe donc par tout afficher sans aucune valeur pour ces paramètres. Une solution de contournement peut consister à enregistrer le symbole avec quelques valeurs fixes à la place des variables. Cela m'a permis de remplacer cet élément de légende d'affichage par défaut: par celui-ci répondant à mes besoins
la source