Ich habe einige Ebenen mit sehr komplexen datendefinierten Symbolen. Wenn ich im Print Composer eine Legende verwende, werden diese Symbole nicht richtig gezeichnet.
Gibt es eine Möglichkeit, die Legenden-Symbole mit Pyqgis zu ändern, sodass ich benutzerdefinierte PNG- oder SVG-Bilder anstelle des Standard-Legenden-Symbols für diese Ebenen verwenden kann?
Ich weiß, wie man dem Druckkomponisten einen Druckknopf hinzufügt und wie man ihn mit einer Funktion verbindet. Ich möchte den Legendeneinstellungen eine Schaltfläche hinzufügen, damit ich das automatisch generierte Legenden-Symbol durch ein benutzerdefiniertes Bild ersetzen kann. Was ich also noch brauche, ist die Information, wie ich mit pyqgis / pyqt auf die Legenden-Symbole zugreifen kann und wie ich sie durch ein QImage auf einem QLabel oder so etwas ersetzen kann?
Sehr einfaches Modell der Schaltfläche zum Ändern des Symbols:
Automatisch generierte Legende:
Legende mit benutzerdefiniertem Legenden-Symbol:
Ich habe bereits herausgefunden, wie ich auf die Elemente der Legende im Druckkomponisten zugreifen kann, aber noch nicht, wie ich auf das Symbol selbst zugreifen kann:
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()
Bearbeiten 1:
Ich habe auch herausgefunden, wie man auf QIcon-Objekte des Legendenbaums zugreift, kann sie aber noch nicht austauschen:
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()
Hier ist ein Beispiel aus dem wirklichen Leben, in dem Sie eine Symbologie sehen können, die aus vielen Symbolebenen kombiniert ist: Dies endet in der Legende wie folgt:
Da ich das richtige Symbol in der Legende benötige, möchte ich einen Screenshot meines Symbols erstellen, es zuschneiden und als Bild in meiner Legende verwenden.
Ich weiß, dass ich einfach ein separates Bild über meine Legende legen könnte, das das automatisch generierte Symbol abdeckt, aber ich hätte gerne eine "sauberere" Lösung, mit der ich die Symbole in der Legende durch benutzerdefinierte Bilder ersetzen kann.
Bearbeiten 2:
In der Zwischenzeit habe ich einen anderen Weg gefunden, um auf die Legendeneinträge zuzugreifen:
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)
Dadurch kann ich auf die QgsLayerTreeLayer-Objekte zugreifen und den Legendenstil (Gruppe, Untergruppe, Versteckt) wechseln. Aber ich habe immer noch keine Ahnung, wie ich auf das Legenden-Symbol zugreifen soll. Irgendwelche Ideen?
Antworten:
Da dieses Thema viele Argumente abdeckt, werde ich mich nur auf die SVG-Symbolebenen konzentrieren, in der Hoffnung, dass ich gut verstanden habe, wonach Sie suchen (ich habe die Länge der Antwort beim Schreiben nicht erkannt, daher tut es mir leid das aber ich hoffe es wird mehr Klarheit hinzufügen).
Kontext
1) Symbolebenenklassen
Die folgenden Symbolebenenklassen sind für das SVG-Format verfügbar:
Ein gängiger Ansatz zum Erstellen einer Symbolebene besteht darin, sie mit einem Wörterbuch mit Eigenschaften zu initialisieren.
Sie können eine neue Symbolebene initialisieren und ihre Standardeigenschaften auf folgende Weise anzeigen:
Sie erhalten alle darin gespeicherten Eigenschaften:
Wenn Sie die Eigenschaften bearbeiten möchten, können Sie Methoden verwenden, die über die Hilfe der Klasse aufgerufen werden können (z. B.
help(QgsSvgMarkerSymbolLayerV2)
in der Python-Konsole ausführen ). Sie werden später ein Beispiel für die Verwendung von Methoden sehen.Der Vollständigkeit halber können Sie auch eine Symbolebene mit einem Wörterbuch von Eigenschaften initialisieren (siehe hier ), aber ich bevorzuge aufrichtig den ersten Ansatz und werde ihn verwenden.
2) Erstellen eines Renderers
Um die Symbolebene zu verwenden, nachdem Sie sie erstellt (und schließlich bearbeitet) haben, müssen Sie einen geeigneten Renderer erstellen und diesen Renderer dann Ihrer Kartenebene zuweisen.
So greifen Sie auf den vorhandenen Renderer einer Ebene zu:
Verwenden Sie Folgendes, um eine Liste der verfügbaren Renderertypen abzurufen:
Für Ihren Fall sollten wir uns mit einem Categorized Symbol Renderer befassen . Wie ich bereits sagte, müssen Sie einen Renderer erstellen und ihn dann der Ebene zuweisen:
3) Ändern der Symbolebene
Die verschiedenen Symbole des Categorized Symbol Renderers können über aufgerufen werden
symbols()
(es wird eine Liste zurückgegeben):Wenn Sie eine bestimmte Symbolebene innerhalb der
symbol
zuvor definierten Ebene ersetzen möchten , müssen Sie nur ihren Index kennen und ihn dann dem Renderer auf folgende Weise mitteilen:Dabei
[0]
gibt es das erste Element der kategorisierten Gruppe an.Lösung
Lassen Sie uns zum Schluss das anwenden, was wir gerade gelernt haben!
Angenommen, Sie arbeiten an dieser Polygonebene, in der die zuvor definierten Landnutzungen gespeichert sind:
Wenn Sie das Standardmuster für die Nutzung landwirtschaftlicher Flächen (sie haben die Position Nr. 1 in der Gruppe "Landnutzung") mit einem bestimmten SVG-Bild ändern möchten, können Sie diesen Code ausführen (lesen Sie hier, um zu erfahren, wie Sie eine benutzerdefinierte SVG hinzufügen Pfad):
Dies wird das Ergebnis sein:
Der obige Code ist sehr grob, aber da ich nicht wusste, ob Sie eine bestimmte Lösung für Ihr Beispiel oder eine allgemeinere Erklärung wünschen, habe ich es vorgezogen, die Aufmerksamkeit auf die verfügbaren Tools zu richten, anstatt den Code selbst zu verfeinern (da bin ich mir sicher Sie können es leicht nach Ihren spezifischen Bedürfnissen bearbeiten!).
quelle
Alternativ und ohne Python-Codierung habe ich dieses Problem gelöst, indem ich eine neue Ebenengruppe für die Legendenerstellung erstellt habe, in der ich alles, was ich möchte, mit den gewünschten Größen und Farben platzieren kann. So habe ich im Print Composer gerade die tatsächlichen Datenebenen aus den Legendenelementen gelöscht und nur die Legendenebenengruppe beibehalten.
Es ist besonders praktisch, wenn eine Legende erstellt werden muss, die Fälle darstellen kann, die in der tatsächlich gedruckten Karte nicht vorkommen.
BEARBEITEN: und bei Ihrer zweiten Bearbeitung, bei der die zusammengesetzten Symbole nicht richtig angezeigt werden, haben Sie einige Variablen, die Ihre Symbole definieren, z. B. das "C" oder "G" ist tatsächlich relativ zu einem Feld oder der Ausrichtung? Wenn dies der Fall ist, kann QGIS nicht erraten, was angezeigt werden soll. Daher wird alles ohne Wert für diese Parameter angezeigt. Eine Problemumgehung kann darin bestehen, das Symbol mit einigen festen Werten anstelle der Variablen zu speichern. Auf diese Weise konnte ich dieses Standardelement für die Anzeige von Legenden ersetzen: durch dieses Element , das meinen Anforderungen entspricht
quelle