i have a column in my attribute table called 'Color' and 'Line' where I store rgb color codes and line thickness values (in map units) to give my layer elements a color and thickness. You can do it manually style => layerproperties.However I would like to use pyqgis to directly plot it properly.
2 Answers
Example for RGB column. Most of it from the answer to Applying catgorized symbol to each feature using PyQGIS, but with layer.getFeatures to read colors from attribute table. I have QGIS 3 so I had to change some of the syntax from pyqgis2 to 3, for example QgsSymbolV2
to QgsSymbol
layer = iface.activeLayer()
category_column = 'kommunnamn'
rgb_column = 'rgb'
color = {f[category_column]:f[rgb_column] for f in layer.getFeatures()} #Store all colors in a dictionary
fni = layer.fields().indexFromName(category_column)
unique_values = list(layer.dataProvider().uniqueValues(fni))
categories = []
for unique_value in unique_values:
symbol = QgsSymbol.defaultSymbol(layer.geometryType())
layer_style = {}
layer_style['color'] = color[unique_value] #Read colors from the dictionary
layer_style['outline'] = '#000000'
symbol_layer = QgsSimpleFillSymbolLayer.create(layer_style)
symbol.changeSymbolLayer(0, symbol_layer)
category = QgsRendererCategory(unique_value, symbol, str(unique_value))
categories.append(category)
renderer = QgsCategorizedSymbolRenderer(category_column, categories)
layer.setRenderer(renderer)
layer.triggerRepaint()
-
I have the current problem that
symbol.changeSymbolLayer(0, symbol_layer)
gives mefalse
as a response. As a result, the default symbol layer is not replaced with the configured one.– TobiasAug 18, 2020 at 11:07
I've set a minimum project available at https://labs.webgeodatavore.com/partage/sample-datadefined-colors.zip. Unzip it. Open the qgs file with QGIS and use the following in the Python QGIS console
layer = iface.activeLayer()
# For color defined in attribute column
layer.renderer().symbol().symbolLayer(0).dataDefinedProperties().property(QgsSymbolLayer.PropertyFillColor).setExpressionString("\"rgb\" || ',255'")
layer.renderer().symbol().symbolLayer(0).dataDefinedProperties().property(QgsSymbolLayer.PropertyFillColor).setActive(True)
# For thickness in attribute column
layer.renderer().symbol().symbolLayer(0).dataDefinedProperties().property(QgsSymbolLayer.PropertyStrokeWidth).setExpressionString("\"thickness\"")
layer.renderer().symbol().symbolLayer(0).dataDefinedProperties().property(QgsSymbolLayer.PropertyStrokeWidth).setActive(True)
# Refresh rendering of the layer
layer.triggerRepaint()
You will just need to use the same recipe by looping on your various layers.
Unrelated to usage with PyQGIS but to choose the approach that "fit", the main drawback using data defined properties if that you don't get a "right" legend but you will be able to manage as many colors as you want. The other approach mentioned with QgsCategorizedSymbolRenderer
is better for legend as long as you don't have hundred or thousand of categories (because predictable).
-
I try to rewrite it into qgis 2.8.8 but I get the Error: QgsSimpleFillSymbolLayerV2' object has no attribute 'dataDefinedProperties'. Does anoyone know what I need to change to make it run in 2.8.8?– TobiasAug 17, 2020 at 10:12
data defined override
(rectangles with tiny triangles next to every field where you may enter a value).