Since you want the border color to match the corresponding polygon fill, you can use the data defined property @symbol_color
, which returns the fill color for each polygon. Then, for the default polygon symbol (which is the base of your QgsRuleBasedRendererV2
) you set its color_border
property to @symbol_color
:
ddp = QgsDataDefined( True, True, "@symbol_color" ) # active, useExpression, expression
symbol.symbolLayer( 0 ).setDataDefinedProperty( "color_border", ddp )
Your script would become this:
from PyQt4.QtGui import QColor
layer = iface.activeLayer()
style_rules = (
('First', 'expression_1', '#dbffdb'),
('Second', 'expression_2', '#f0ab64'),
)
symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
ddp = QgsDataDefined( True, True, "@symbol_color" )
symbol.symbolLayer( 0 ).setDataDefinedProperty( "color_border", ddp )
renderer = QgsRuleBasedRendererV2(symbol)
root_rule = renderer.rootRule()
for label, expression, color_name in style_rules:
rule = root_rule.children()[0].clone()
rule.setLabel(label)
rule.setFilterExpression(expression)
rule.symbol().setColor(QColor(color_name))
root_rule.appendChild(rule)
root_rule.removeChildAt(0)
layer.setRendererV2(renderer)
layer.triggerRepaint()
On the other hand, to set the same border color for all polygons in a Rule based renderer, you would use setBorderColor()
in this way (after initializing symbol
variable):
symbol.symbolLayer( 0 ).setBorderColor( QColor(255,0,0) )
Just tested it on QGIS v2.14.8. Let me know if it works on your QGIS installation.
Below some help to setup rule based labeling from scratch with the new QGIS 3 API
#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()
Unfortunately I can't find how to iterate over existing rules, the labeling() method available for vector layers return an object of QgsAbstractVectorLayerLabeling class but it seems there is no way to get the root rule (QgsRuleBasedLabeling) from this class, the only possibility I found is to get directly pal settings using providers ids but I can't access to rules tree. Anyone have a clue ?
EDIT
It's now fixed, labeling() function return a QgsRuleBasedLabeling() : https://github.com/qgis/QGIS/commit/4b365a8f47d96b35f7609859e580388927ae0606
Best Answer
Your code works fine. When you want to add a new rule, do not repeat the first 3 lines of code as this creates a new symbol renderer. Just start from
And create your new rule.
I find it easier to use a function like the following:
Then you can apply new rules: