Mengontrol pelabelan berbasis aturan menggunakan PyQGIS?

15

Sebagai lanjutan dari pertanyaan ini: Cara menghidupkan / mematikan semua label dari semua lapisan di QGIS , OP menyebutkan dalam komentarnya bahwa dia menggunakan label berbasis aturan. Saya mencoba mencari di internet bagaimana jenis label ini dapat dibaca dan dimodifikasi tetapi hanya berhasil menemukan posting ini dari lutraconsulting :

Untuk memfasilitasi penambahan pelabelan berbasis aturan, beberapa perubahan internal dilakukan pada antarmuka mesin pelabelan QGIS. Pelabelan sekarang didorong oleh kelas baru QgsLabelingEngineV2yang mungkin memiliki beberapa penyedia label yang terkait dengannya.

Kedengarannya bagus. Namun, ketika membaca kelas QgsLabelingEngineV2 , disebutkan:

kelas ini belum menjadi bagian dari API publik.

Apakah saat ini dimungkinkan untuk mengontrol pelabelan berbasis aturan menggunakan python?

Yusuf
sumber
1
Saya menemukan masalah terbuka di sini pada proyek Dokumentasi Qgis di Github yang juga menyebutkan ini . Saya tidak dapat menemukan SIP yang mengikat untuk kelas itu di MASTER atau 2,18 cabang, jadi saya curiga itu hanya tersedia untuk kode C ++.
Steven Kay
@ SevenKay - Great find, terima kasih! Akan sangat berguna jika mereka membuat API untuk itu ... Juga terima kasih untuk hasil edit, saya pikir saya menempelkan tautan yang benar untuk kelas :)
Joseph
@StevenKay - Saya pikir mereka membuat API untuk ini sekarang, lebih khusus Kelas QgsRuleBasedLabeling :)
Joseph

Jawaban:

6

Di bawah ini beberapa bantuan untuk mengatur pelabelan berbasis aturan dari awal dengan QGIS 3 API baru

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

Sayangnya saya tidak dapat menemukan cara mengulangi aturan yang ada, metode pelabelan () yang tersedia untuk layer vektor mengembalikan objek QgsAbstractVectorLayerLabeling kelas tetapi tampaknya tidak ada cara untuk mendapatkan aturan root ( QgsRuleBasedLabeling ) dari kelas ini, satu-satunya kemungkinan Saya menemukan adalah untuk mendapatkan langsung pengaturan sobat menggunakan id penyedia tetapi saya tidak dapat mengakses ke pohon aturan. Adakah yang punya petunjuk?

EDIT

Sekarang sudah diperbaiki, fungsi pelabelan () mengembalikan QgsRuleBasedLabeling (): https://github.com/qgis/QGIS/commit/4b365a8f47d96b35f7609859e580388927ae0606

domlysz
sumber
Terima kasih atas jawaban Anda, berhasil dengan baik! Semoga Anda tidak keberatan, tetapi saya sedikit mengedit pos Anda untuk memasukkan myLayer.triggerRepaint()untuk menyegarkan lapisan dan memungkinkan label untuk segera ditampilkan setelah menetapkan aturan :)
Joseph
3

Dari QGIS 3 , ada Kelas QgsRuleBasedLabeling baru yang akan memungkinkan Anda untuk mengontrol pelabelan berbasis aturan menggunakan API baru.

Aturan dapat ditambahkan menggunakan QgsRuleBasedLabeling :: Rule .


( Sayangnya, saya tidak dapat menguji versi 2.99 saat ini. Tetapi saya akan dengan senang hati menerima jawaban jika memberikan contoh yang berfungsi. )

Yusuf
sumber
1

Inilah yang saya gunakan untuk mengubah ekspresi filter dalam simbologi berbasis aturan di bawah QGIS 2.18, tidak yakin apakah itu yang Anda minta. Referensi API di 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
sumber
Terima kasih atas jawaban Anda tetapi seperti yang Anda katakan, saya pikir ini hanya berlaku untuk simbologi dan bukan label :)
Joseph