Управление маркировкой на основе правил с помощью PyQGIS?

15

Исходя из этого вопроса: Как включить / выключить все метки всех слоев в QGIS , OP упомянул в своем комментарии, что он использует метки на основе правил. Я попытался найти в Интернете, как эти типы ярлыков можно прочитать и изменить, но мне удалось найти этот пост только у lutraconsulting :

Для облегчения добавления маркировки на основе правил были внесены некоторые внутренние изменения в интерфейс механизма маркировки QGIS. Маркировка теперь управляется новым классом, QgsLabelingEngineV2который может иметь несколько провайдеров меток, связанных с ним.

Звучит здорово. Однако при чтении через класс QgsLabelingEngineV2 упоминается:

этот класс еще не является частью публичного API.

Возможно ли в настоящее время контролировать маркировку на основе правил с помощью python?

Джозеф
источник
1
Я нашел открытую проблему здесь в проекте документации Qgis в Github, в которой также упоминается об этом . Я не смог найти привязку SIP для этого класса в ветвях MASTER или 2.18, поэтому я подозреваю, что она все еще доступна только для кода C ++.
Стивен Кей
@ StevenKay - Отличная находка, спасибо! Было бы весьма полезно, если бы они сделали API для этого ... Также спасибо за редактирование, я думал, что вставил правильную ссылку для класса :)
Джозеф
@StevenKay - я думаю, что они создали API для этого сейчас, точнее, класс QgsRuleBasedLabeling :)
Джозеф

Ответы:

6

Ниже приведена некоторая помощь по настройке надписей на основе правил с нуля с помощью нового 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()

К сожалению, я не могу найти способ перебора существующих правил, метод labeling (), доступный для векторных слоев, возвращает объект класса QgsAbstractVectorLayerLabeling, но, похоже, нет способа получить корневое правило ( QgsRuleBasedLabeling ) из этого класса, единственная возможность Я обнаружил, что нужно напрямую получать настройки друзей, используя идентификаторы провайдеров, но я не могу получить доступ к дереву правил. У кого-нибудь есть подсказка?

РЕДАКТИРОВАТЬ

Теперь это исправлено, функция labeling () возвращает QgsRuleBasedLabeling (): https://github.com/qgis/QGIS/commit/4b365a8f47d96b35f7609859e580388927ae0606

domlysz
источник
Спасибо за ваш ответ, отлично сработано! Надеюсь, вы не возражаете, но я немного отредактировал ваш пост, чтобы включить его, myLayer.triggerRepaint()чтобы обновить слой и позволить отображать метки сразу после установки правил :)
Джозеф,
3

В QGIS 3 появился новый класс QgsRuleBasedLabeling, который позволит вам управлять маркировкой на основе правил с помощью нового API.

Правила могут быть добавлены с использованием QgsRuleBasedLabeling :: Rule .


( К сожалению, в настоящее время я не могу протестировать версию 2.99. Но я бы с радостью принял ответ, если бы он предоставил работающий пример. )

Джозеф
источник
1

Это то, что я использую для изменения выражения фильтра в символике на основе правил в QGIS 2.18, но не уверен, что это то, что вы просите. Ссылка на API по адресу 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
источник
Спасибо за ваш ответ, но, как вы сказали, я думаю, что это относится только к символике, а не к меткам :)
Джозеф