Controllo dell'etichettatura basata su regole tramite PyQGIS?


15

In seguito a questa domanda: Come attivare / disattivare tutte le etichette di tutti i livelli in QGIS , OP ha menzionato nel suo commento che utilizza etichette basate su regole. Ho provato a cercare online come leggere e modificare questi tipi di etichette, ma sono riuscito a trovare questo post solo da lutraconsulting :

Per facilitare l'aggiunta dell'etichettatura basata su regole, sono state apportate alcune modifiche interne all'interfaccia del motore di etichettatura QGIS. L'etichettatura è ora guidata dalla nuova classe alla QgsLabelingEngineV2quale possono essere associati diversi fornitori di etichette.

Suona alla grande. Tuttavia, quando legge la classe QgsLabelingEngineV2 , menziona:

questa classe non fa ancora parte dell'API pubblica.

È attualmente possibile controllare l'etichettatura basata su regole usando Python?


1
Ho trovato un problema aperto qui sul progetto di documentazione Qgis a Github che menziona anche questo . Non sono riuscito a trovare un'associazione SIP per quella classe nei rami MASTER o 2.18, quindi sospetto che sia ancora disponibile solo per il codice C ++.
Steven Kay,

@StevenKay - Grande scoperta, grazie! Sarebbe molto utile se creassero un'API per questo ... Grazie anche per la modifica, ho pensato di aver incollato il link corretto per la classe :)
Joseph

@StevenKay - Penso che abbiano creato un'API per questo ora, più precisamente la classe QgsRuleBasedLabeling :)
Joseph

Risposte:


6

Di seguito alcuni suggerimenti per configurare da zero l'etichettatura basata su regole con la nuova API QGIS 3

#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()

Sfortunatamente non riesco a trovare come scorrere le regole esistenti, il metodo labeling () disponibile per i livelli vettoriali restituisce un oggetto della classe QgsAbstractVectorLayerLabeling ma sembra che non ci sia modo di ottenere la regola radice ( QgsRuleBasedLabeling ) da questa classe, l'unica possibilità Ho scoperto che è possibile ottenere direttamente le impostazioni degli amici utilizzando gli ID provider, ma non riesco ad accedere all'albero delle regole. Qualcuno ha un indizio?

MODIFICARE

Ora è stato risolto, la funzione labeling () restituisce un QgsRuleBasedLabeling (): https://github.com/qgis/QGIS/commit/4b365a8f47d96b35f7609859e580388927ae0606


Grazie per la tua risposta, ben risolto! Spero non ti dispiaccia, ma ho modificato leggermente il tuo post per includerlo myLayer.triggerRepaint()per aggiornare il livello e consentire alle etichette di essere mostrate immediatamente dopo aver impostato le regole :)
Joseph,

3

Da QGIS 3 , esiste una nuova classe QgsRuleBasedLabeling che ti consentirebbe di controllare l'etichettatura basata su regole utilizzando la nuova API.

Le regole possono essere aggiunte usando QgsRuleBasedLabeling :: Rule .


( Purtroppo, al momento non posso testare la versione 2.99. Ma accetterei felicemente una risposta se fornisse un esempio funzionante. )


1

Questo è ciò che uso per modificare un'espressione di filtro nella simbologia basata su regole in QGIS 2.18, non sono sicuro che sia quello che stai chiedendo. Riferimento API su 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)

Grazie per la risposta, ma come hai detto, penso che questo si applichi solo alla simbologia e non alle etichette :)
Joseph
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.