4

I want to label a shp layer on two lines with pyQGis. I managed to do it with only one field, but with two or more fields (using concat) it does not work anymore.

Here is the code I wrote:

def labelLine (lyr, fieldNom1, fieldNom2):
  # This function shows the labels of 2 fields "fieldName1" and "fieldName2" for a Line layer lyr
  label = QgsPalLayerSettings ()
  label.readFromLayer (lyr)
  label.enabled = True
  # we concatenate the two fields
  label.fieldName = "concat ('BASE:', fieldName1, '\\ n', 'L =', fieldName2, 'm')"
  label.placement = QgsPalLayerSettings.Line
  label.bufferDraw = True
  label.bufferSize = 1
  label.setDataDefinedProperty (QgsPalLayerSettings.S ize, True, True, '8', '')
  label.writeToLayer (lyr)
  • 1
    Maybe try replacing \\ n with \n? So label.fieldName = "concat('BASE:', fieldName1, '\n', 'L =', fieldName2, 'm')". – Joseph Oct 17 '17 at 11:07
  • Thank you, I tried your proposal but it did not work. – ennine Oct 17 '17 at 12:50
  • What happens when you use it? Is it still on a single line? Is there an error in the expression? Maybe you can post a screenshot of how the label looks? – Joseph Oct 17 '17 at 13:30
  • - With one field, it works very well: label.fieldName = champNom1 The label, in this case it is the length of each segment of an electric line, appears correctly. - With the concat expression, there is no error after the code compilation but there is no label on the line segments. – ennine Oct 17 '17 at 18:39
  • This question is a duplicate of gis.stackexchange.com/questions/132905/… – YoLecomte Oct 17 '17 at 20:53
3

Perhaps try something like the following expression. We can use the to_string function from the Field Calculator to convert any value from a field to a string (as you can't concatenate strings and values):

'''concat('BASE: ' + to_string("''' + fieldName1 + '''"),'\nL = ' + to_string("''' + fieldName2 + '''") + 'm')'''

So your code could look like:

def labelLine(lyr, fieldName1, fieldName2):
    label = QgsPalLayerSettings()
    label.readFromLayer(lyr)
    label.enabled = True
    label.fieldName = '''concat('BASE: ' + to_string("''' + fieldName1 + '''"),'\nL = ' + to_string("''' + fieldName2 + '''") + 'm')'''
    label.placement = QgsPalLayerSettings.Line
    label.bufferDraw = True
    label.bufferSize = 1
    label.setDataDefinedProperty(QgsPalLayerSettings.Size, True, True, '8', '')
    label.writeToLayer(lyr)
    lyr.setCustomProperty("labeling/drawLabels", True)
    lyr.triggerRepaint()

lyr = iface.activeLayer()
labelLine(lyr, 'fieldName1', 'fieldName2')

Example:

Example

  • 1
    Many thanks Joseph for your very helpful code. However, the label do not appear automatically in QGis and I have to switch the Layer Properties/Labels, and toggle OK. I try to add the following to confirm the changes but it does not work: layer.triggerRepaint() or layer.commitChanges() layer.updateExtents() Any help would be appreciated. – ennine Oct 23 '17 at 14:08
  • 1
    @ennine - Most welcome! Edited the post to include additional lines of code which should hopefully enable and draw the labels :) – Joseph Oct 23 '17 at 14:38
  • see this link: gis.stackexchange.com/questions/259369/… – ennine Oct 23 '17 at 19:11
  • @ennine - Did you see my edit and test the two lines of code I added? I don't see them in the question you posted :) – Joseph Oct 24 '17 at 9:04
  • 1
    @ennine - This worked for me previously on QGIS 2.18.2. I recently updated to 2.18.13 and now it doesn't work. I wonder if this is a bug... – Joseph Oct 24 '17 at 14:22
3

What about using the wrapChar() method of QgsPalLayerSettings (http://qgis.org/api/2.18/classQgsPalLayerSettings.html) You can set a character that is intended to wrap the label string

something like:

label.wrapChar = '*'

and then in your code:

label.fieldName = "concat ('BASE:', fieldName1, '*', 'L =', fieldName2, 'm')"

then run, it may work

  • Unfortunetly, after the code compilation, I received the following error: – ennine Oct 17 '17 at 19:38
  • label. WrapChar('*') AttributeError: 'QgsPalLayerSettings' object has no attribute 'WrapChar' – ennine Oct 17 '17 at 19:39
  • Remove the upper W and replace with lower w – YoLecomte Oct 17 '17 at 19:45
  • When I replace WrapChar by wrapChar, I receive the following error: label. wrapChar('*') TypeError: 'unicode' object is not callable – ennine Oct 17 '17 at 19:45
  • if you do a copy/paste of the error, you have a space between the dot and wrapChar... remove it. – YoLecomte Oct 17 '17 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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