Regelbasierte Kennzeichnung mit PyQGIS steuern?

15

Ausgehend von dieser Frage: Wie Sie alle Bezeichnungen aller Ebenen in QGIS aktivieren / deaktivieren , erwähnte OP in seinem Kommentar, dass er regelbasierte Bezeichnungen verwendet. Ich habe versucht, online zu suchen, wie diese Arten von Labels gelesen und geändert werden können, habe es aber nur geschafft, diesen Beitrag von lutraconsulting zu finden :

Um das Hinzufügen regelbasierter Beschriftungen zu erleichtern, wurden einige interne Änderungen an der Schnittstelle der QGIS Labelling Engine vorgenommen. Die Kennzeichnung wird nun von der neuen Klasse gesteuert, QgsLabelingEngineV2der möglicherweise mehrere Etikettenanbieter zugeordnet sind.

Klingt gut. Beim Durchlesen der QgsLabelingEngineV2-Klasse wird jedoch Folgendes erwähnt:

Diese Klasse ist noch kein Teil der öffentlichen API.

Ist es derzeit möglich, die regelbasierte Beschriftung mit Python zu steuern?

Joseph
quelle
1
Ich habe hier eine offene Frage zum Qgis-Dokumentationsprojekt in Github gefunden, in der dies ebenfalls erwähnt wird . Ich konnte keine SIP-Bindung für diese Klasse in den Verzweigungen MASTER oder 2.18 finden, daher vermute ich, dass sie nur für C ++ - Code verfügbar ist.
Steven Kay
@StevenKay - Tolle Entdeckung, danke! Wäre ganz nützlich, wenn sie eine API dafür machen würden ... Auch danke für die Bearbeitung, ich dachte, ich habe den richtigen Link für die Klasse eingefügt :)
Joseph
@StevenKay - Ich denke, sie haben jetzt eine API dafür erstellt, genauer gesagt die QgsRuleBasedLabeling-Klasse :)
Joseph

Antworten:

6

Nachfolgend finden Sie einige Hilfestellungen zum Einrichten der regelbasierten Beschriftung mit der neuen QGIS 3-API

#Configure label settings
settings = QgsPalLayerSettings()
settings.fieldName = 'myFieldName'
textFormat = QgsTextFormat()
textFormat.setSize(10)
settings.setFormat(textFormat)
#create and append a new rule
root = QgsRuleBasedLabeling.Rule(QgsPalLayerSettings())
rule = QgsRuleBasedLabeling.Rule(settings)
rule.setDescription(fieldName)
rule.setFilterExpression('myExpression')
root.appendChild(rule)
#Apply label configuration
rules = QgsRuleBasedLabeling(root)
myLayer.setLabeling(rules)
myLayer.triggerRepaint()

Leider kann ich nicht herausfinden, wie vorhandene Regeln durchlaufen werden. Die label () -Methode für Vektorebenen gibt ein Objekt der QgsAbstractVectorLayerLabeling- Klasse zurück, aber es scheint, als gäbe es keine Möglichkeit, die Stammregel ( QgsRuleBasedLabeling ) von dieser Klasse zu erhalten. Dies ist die einzige Möglichkeit Ich habe festgestellt, dass es sich um direkte Pal-Einstellungen handelt, bei denen Anbieter-IDs verwendet werden. Ich kann jedoch nicht auf den Regelbaum zugreifen. Hat jemand eine Ahnung?

BEARBEITEN

Es ist jetzt behoben, Labeling () - Funktion gibt ein QgsRuleBasedLabeling () zurück: https://github.com/qgis/QGIS/commit/4b365a8f47d96b35f7609859e580388927ae0606

domlysz
quelle
Vielen Dank für Ihre Antwort, gut ausgearbeitet! Ich hoffe, es macht Ihnen nichts aus, aber ich habe Ihren Beitrag leicht bearbeitet myLayer.triggerRepaint(), um die Ebene zu aktualisieren und zuzulassen, dass die Beschriftungen sofort nach dem Festlegen der Regeln angezeigt werden :)
Joseph
3

Ab QGIS 3 gibt es eine neue QgsRuleBasedLabeling-Klasse, mit der Sie die regelbasierte Kennzeichnung mithilfe der neuen API steuern können.

Regeln können mit QgsRuleBasedLabeling :: Rule hinzugefügt werden .


( Leider kann ich die 2.99-Version derzeit nicht testen. Ich würde jedoch gerne eine Antwort annehmen, wenn sie ein funktionierendes Beispiel liefert. )

Joseph
quelle
1

Dies ist, was ich verwende, um einen Filterausdruck in der regelbasierten Symbologie unter QGIS 2.18 zu ändern, nicht sicher, ob Sie danach fragen. API-Referenz unter http://qgis.org/api/2.18/classQgsRuleBasedRendererV2.html

import re
lddLrs = qgis.utils.iface.legendInterface().layers()    #get all loaded layers
for lyr in lddLrs:
    if (lyr.type()==QgsMapLayer.VectorLayer and lyr.name()=='layer_with_rules'): rLyr = lyr

newType = 1
for child in rLyr.rendererV2().rootRule().children():
    oldFilter = child.filterExpression()  #you can print this to see what the old expression is
    print oldFilter

    newFilter = re.sub(r"type = (\d*)", r"type = {0}".format(newType), oldFilter)  #this is an example to substitute a rule-based filter to a new number
    print newFilter

    child.setFilterExpression(newFilter)
weiji14
quelle
Vielen Dank für Ihre Antwort, aber wie Sie sagten, ich denke, dies gilt nur für Symbologie und nicht Etiketten :)
Joseph