3

My goal is to add Callouts (Manhattan type) to labels in a point layer with PyQGIS.

Here is what I got so far, which basically renders the labels without the callouts:

font = QgsTextFormat()
font.setFont(QFont('MS Shell Dlg 2'))
font.setSize(12)
p_layer = QgsPalLayerSettings()
p_layer.setFormat(font)
p_layer.fieldName = 'label'
p_layer.enabled = True
labels = QgsVectorLayerSimpleLabeling(p_layer)
layer.setLabeling(labels)
layer.setLabelsEnabled(True)
layer.triggerRepaint()

What I have tried:

I read in the documentation that the QgsPalLayerSettings class has a method named setCallout, which if I understand correctly, takes an object of QgsCallout class as argument.

When I try to start setting/using the QgsCallout() class, I get the following message in the QGIS Python console:

TypeError: qgis._core.QgsCallout represents a C++ abstract class and cannot be instantiated

According to this answer in StackOverflow:

"The error means there are some methods of the class that aren't implemented. ..."


Question: How to add Callouts to labels with PyQGIS? I'm using QGIS version 3.14.1

1 Answer 1

5

You can instantiate the QgsManhattanLineCallout() class instead of the abstract parent QgsCallout() class.

Try the example code below:

layer = QgsProject().instance().mapLayersByName('Your_layer_name')[0]

txt_format = QgsTextFormat()
txt_format.setFont(QFont('MS Shell Dlg 2', 10))
txt_format.setColor(QColor('black'))

settings = QgsPalLayerSettings()
settings.setFormat(txt_format)
settings.fieldName = 'labels'
settings.drawLabels = True

callouts = QgsManhattanLineCallout()
callouts.setEnabled(True)

settings.setCallout(callouts)

labels = QgsVectorLayerSimpleLabeling(settings)
layer.setLabeling(labels)
layer.setLabelsEnabled(True)

layer.triggerRepaint()
iface.mapCanvas().refresh()

After running the script above and moving a couple of labels, the callout lines were drawn as seen below on my test layer:

enter image description here

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.