Mehr

Nur einige Layer in der QGIS-Legende anzeigen?

Nur einige Layer in der QGIS-Legende anzeigen?


Meine QGIS 2.8.2 Standalone-App bietet verschiedene Dekorationsebenen (z. B. kartografisches Raster, Hintergrundebenen, Referenzpunkte), die vom Benutzer nicht geändert werden sollten (weder bearbeiten noch ausblenden), sowie Ebenen, die der Benutzer ändern und abfragen kann.

Die App verfügt über ein Legenden-Widget, das alle Layer anzeigt, da alle Layer bei der Kartenregistrierung registriert sind. Das Widget wird mit dem Layer-Baum gefüllt, wie in Wie füge ich eine Legende zu einer Leinwand in einer eigenständigen PyQGIS-Anwendung hinzu?.

Anstatt alle Ebenen in der Baumansicht anzuzeigen, möchte ich die Baumansicht auf die Ebenengruppe beschränken, deren Kinder die vom Benutzer veränderbaren Ebenen darstellen. Somit kann der Benutzer die Sichtbarkeit und Anordnung nur dieser Schichten ändern und muss die Dekoration unverändert beibehalten.

Was ich bisher versucht habe, ist, QgsLayerTreeMapCanvasBridge mit diesem Gruppenknoten (anstelle von layerTreeRoot) zu initiieren, den Gruppenknoten an QgsLayerTreeModel() zu übergeben oder die Stammgruppe des Modells mit QgsLayerTreeModel.setRootGroup() zu ändern. In jedem Fall stürzt Python mit einer Fehlermeldung wie dieser ab:

QObject::connect: Kann keine Verbindung (null)::willAddChildren( QgsLayerTreeNode*, int, int ) zu QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode*, int, int ) herstellen

Ist es möglich, nur einige Gruppen- oder Layer-Knoten in der Baumansicht anzuzeigen und wie kann ich dies implementieren?


In der Zwischenzeit habe ich eine Lösung gefunden, vielleicht eine Problemumgehung für meine App, um eine Legende mit nur Teilen der Ebenen anzuzeigen, die auf dem Karten-Canvas gezeichnet sind. Für das interessierte Publikum möchte ich eine Zusammenfassung geben.

Beim Hinzufügen von Maplayern zu mapLayerRegistry wird automatisch ein MaplayerTree erstellt, wenn der Parameter addToLegend True bleibt. Ich habe es auf False gesetzt, um in einem separaten Schritt einen Layerbaum mit Layer- und Gruppenknoten zu erstellen.

QgsMapLayerRegistry.instance().addMapLayer(layer, False)… self.layer_tree_root = QgsProject.instance().layerTreeRoot() group = self.layer_tree_root.addGroup(group_name) group.addLayer(layer)

Dieser Baum enthält alle Daten und Methoden, die erforderlich sind, um die Sichtbarkeit aller Layer auf Mapcanvas zu steuern. Z.B. um die Sichtbarkeit programmgesteuert zu steuern

QgsProject.instance().layerTreeRoot().findLayer(layer.id()).setVisible(2)

ohne ein LayerSet zu verfolgen, das jedes Mal aktualisiert und an mapcanvas übergeben werden muss, wenn sich der Status eines Layers ändert.

Um die Sichtbarkeit und andere Dinge über eine Legende zu steuern, müssen wir den Baum in einem Baum-Widget anzeigen und ihn über ein QgsLayerTreeMapCanvasBridge-Objekt mit dem Canvas synchronisieren.

Nur einen Teil des Baums über das treeWidget zu steuern, war das, was ich nicht zum Laufen bringen konnte. Als Workaround erstelle ich explizit einen zweiten Baum mit nur dem Gruppenknoten, den ich freigeben möchte:

# initialisiert in myCanvasClass.__init__() self.maps_treeview = QTreeView() # in myCanvasClass.someMethod() wo Layer zur mapLayer Registry hinzugefügt werden self.model = QgsLayerTreeModel(QgsProject.instance().layerTreeRoot().findGroup('Map ')) self.model.setFlag(QgsLayerTreeModel.AllowNodeChangeVisibility) self.model.setFlag(QgsLayerTreeModel.ShowLegend) self.maps_treeview.setHeaderHidden(True) self.maps_treeview.setModel(self.model)

Und irgendwo außerhalb der Klassendefinition, innerhalb aller UI-bezogenen Dinge:

self.canvas = myCanvasClass() self.gridLayout_5.addWidget(self.canvas.maps_treeview, 0, 0, 1, 1)

Es klappt!. Ich kann Ebenen per Code steuern, indem ich Methoden des (unsichtbaren) vollständigen Ebenenbaums verwende. Außerdem kann der Benutzer nur eine Teilmenge von Layern durch Aktivieren von Kontrollkästchen interaktiv ein- und ausschalten.

Da diese Mischung möglicherweise störanfällig ist, bin ich dennoch an einer eleganteren und fundierteren Lösung interessiert.