10

I am trying to use PyQGIS to convert a Fill Symbol Layer into a geometry generator Symbol Layer in a rule-based renderer with 300 rules.

I am able to iterate over the rules and return each rule's symbol and then the respective (unique) Symbol Layer. I know there's a changeSymbolLayer()

What I am failing to do, is to create a QgsGeometryGeneratorSymbolLayer to overwrite the existing symbol layer. Until now, the code is something like this:

layer = iface.mapCanvas().currentLayer()
rules = layer.renderer().rootRule().children()

for rule in rules:
    label = rule.label()
    symbol_layer = rule.symbol().symbolLayer(0)
    print(symbol_layer)
    color = symbol_layer.color()
    generator = QgsGeometryGeneratorSymbolLayer()
    generator.setFillColor(color)
    generator.setGeometryExpression(expression)
    rule.symbol().changeSymbolLayer(0,generator)

In this case the QgsGeometryGeneratorSymbolLayer() fails by saying that I am not able to instantiate.

I am not understanding how to create the new symbol to apply on each rule.

5
  • It doesn't seem to have a constructor. Can you use .create() or .clone() instead? Commented Jan 19, 2021 at 17:35
  • 2
    generator = QgsGeometryGeneratorSymbolLayer.create({}) seems to work
    – Dror Bogin
    Commented Jan 19, 2021 at 17:37
  • To clone() l need an existing symbol layer already, right? Not sure how to use create. I have seen it in other symbol layers types, but wasn't able to figure out how to apply to geometry generators. Commented Jan 19, 2021 at 17:41
  • 1
    Since you are programmatically setting its properties, @DrorBogin's creation of an "empty" generator for you to fill looks good. Commented Jan 19, 2021 at 17:50
  • The documentation about the actual create properties is a bit lacking, but it seems you can create an empty one and just set everything later
    – Dror Bogin
    Commented Jan 19, 2021 at 17:54

1 Answer 1

13

Seems like the only way to create an empty QgsGeometryGeneratorSymbolLayer is by using:

QgsGeometryGeneratorSymbolLayer.create({})

So changing just that should make the rest of the code work:

layer = iface.mapCanvas().currentLayer()
rules = layer.renderer().rootRule().children()

for rule in rules:
    label = rule.label()
    symbol_layer = rule.symbol().symbolLayer(0)
    print(symbol_layer)
    color = symbol_layer.color()
    generator = QgsGeometryGeneratorSymbolLayer.create({})
    generator.setFillColor(color)
    generator.setGeometryExpression(expression)
    rule.symbol().changeSymbolLayer(0,generator)
1
  • 2
    .create({}) was the missing piece. Worked like a charm! Commented Jan 20, 2021 at 1:51

Your Answer

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

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