I found the solution to this question after I took a good look at the existing documentation. Steps that need to be conducted:
- Create CategorizedRenderer
- Update existing CategorizedRenderer and change it into RuleBasedRenderer
- Build a for loop that goes through all the symbologies (in my case symbologies of countries) using the
ruleRend.refineRuleRanges()
function.
Here is an example of what my code looks like:
#create regional_BC_year layer with symbology
layer3 = QgsVectorLayer(output_folder + 'Regional_BC_Joined_' + str(year) + '.shp', "Regional_BC_produced_" + str(year), "ogr")
# read correct field name in regional_bc layer
field_name = 'CNTR_CODE'
field_index = layer3.fields().indexFromName(field_name)
unique_values = layer3.uniqueValues(field_index)
# create category list
category_list = []
for value in unique_values:
symbol = QgsSymbol.defaultSymbol(layer3.geometryType())
category = QgsRendererCategory(value, symbol, str(value))
category_list.append(category)
# create renderer by specifying category list
renderer = QgsCategorizedSymbolRenderer(field_name, category_list)
style = QgsStyle().defaultStyle()
ramp = style.colorRamp('RdYlGn')
renderer.updateColorRamp(ramp)
# set new renderer of layer
layer3.crs = {'init' :'epsg:4326'}
layer3.setRenderer(renderer)
layer3.triggerRepaint()
# change to from categorizedrenderer into rulebased renderer
if renderer.type() == 'categorizedSymbol':
ruleRend = QgsRuleBasedRenderer.convertFromRenderer(renderer)
# add layer to map and set new rulebased renderer
QgsProject.instance().addMapLayer(layer3)
layer3.setRenderer(ruleRend)
layer3.triggerRepaint()
# refresh symbology of layer
iface.layerTreeView().refreshLayerSymbology(layer3.id())
# load values of BC_per_reg column and add to vals df
vals = []
fld = 'BC_per_reg'
for f in layer3.getFeatures():
vals.append(f[fld])
# colors of series that will be visualized
colors = ['#f7fcf5', '#d5efcf', '#9ed898', '#54b567', '#1d8641']
# calculate upper and lower values of vals df
vals = list(filter(None, vals))
vals = [float(s) for s in vals]
lower = 0.001
upper = 15
# add bounds and colors to each range and add to each "symbol"
step = 2
range_list = []
for c in colors:
cat = [lower, lower+step, c]
sym = QgsSymbol.defaultSymbol(layer3.geometryType())
sym.setColor(QColor(cat[2]))
rng = QgsRendererRange(cat[0], cat[1], sym, '{0:.1f}-{1:.1f}'.format(cat[0], cat[1]))
range_list.append(rng)
lower = (lower+step)
# add all symbols, and add to range_list
symbol = QgsSymbol.defaultSymbol(layer3.geometryType())
symbol.setColor(QColor('#00441b'))
rng1 = QgsRendererRange(10, 100, symbol, '{0:.1f}-{1:.1f}'.format(10, 100))
range_list.append(rng1)
# refineRuleRanges so that for eacht class --> e.g. France we will get 5 ranges of values inside
# Scale symbol based on column
if ruleRend.type() == 'RuleRenderer':
for i in range(len(ruleRend.rootRule().children())):
ruleRend.refineRuleRanges(layer3.renderer().rootRule().children()[i], QgsGraduatedSymbolRenderer(fld, range_list)) #inputs for QgsGraduatedSymbolRenderer(fld, range_list)
v1 = layer3
# set renderer and reload layers on map
QgsProject.instance().addMapLayer(v1)
v1.setRenderer(ruleRend)
v1.triggerRepaint()
iface.layerTreeView().refreshLayerSymbology(v1.id())
A visual representation of what the results look like:
I can now check and uncheck all countries while the ranges are visible for other countries! See unchecked regions Portugal: