1

I want to iterate through a field and based on the attributes, assign a color to the feature. I can find how to change colors of a layer, but not for a single feature. Code below.

from PyQt5.QtGui import *
from qgis.core import * 
import os

path = r"path"

layer = QgsVectorLayer(path, os.path.basename(path), "ogr")
layer.startEditing()

features = layer.getFeatures()

for f in features:

    color = f.attributes()[17]

    if color == 53790:
        iface.mapCanvas().setSelectionColor(color_rgb(030, 210, 000))

    else:
        iface.mapCanvas().setSelectionColor(color_rgb(230,155,240)))


layer.updateFields()
1

The following request should help you. Remember to replace the value of the field and the value of the feature.

You don't need to be in edit mode and you were doing a field update at the end when you didn't perform any operations on your fields.

# Your laver 
layer = iface.activeLayer()

# Expression to select a feature
# My field is "ID" and I want to select the feature which has 1 in ID
layer.selectByExpression('"ID" = 1',QgsVectorLayer.SetSelection)

# Change the color of my selection
iface.mapCanvas().setSelectionColor( QColor("blue") )

# Refresh in order the see the changes
iface.mapCanvas().refreshAllLayers()

| improve this answer | |
1

I don't recommend using setSelectionColor() for this. Tasks like this are what different renderer types are for. I think setting up a rule based renderer would work well for your use case.

Try the code below. You can add additional rules for different values in your "color" attribute column as needed.

The structure and syntax of the nested rules list is a list of lists. Each inner list contains three items: a string value for the legend label, an expression enclosed in triple quotes which filters on values in an attribute field, and a QColor object. Each list item and each inner list must be separated by a comma.

Example:

rules = [['53790', """"Color" LIKE '53790'""", QColor(30, 210, 0)],
        ['52780', """"Color" LIKE '52780'""", QColor(230, 155, 240)],
        ['51770', """"Color" LIKE '51770'""", QColor(95, 20, 175)],
        ['50760', """"Color" LIKE '50760'""", QColor(5, 185, 145)]]

So for your case, based on your question, you could set up one rule for features having the value '53790' in a field called "Color" and a catch-all rule for the rest of the features not having that attribute value:

layer = iface.activeLayer()

symbol = QgsSymbol.defaultSymbol(layer.geometryType())
renderer = QgsRuleBasedRenderer(symbol)
#--------------------------------------------------------------
# Set up this nested list of rules to suit your requirements
# changing the legend label, expression and color for each rule
# as desired.
# --------------------------------------------------------------
rules = [['53790', """"Color" LIKE '53790'""", QColor(30, 210, 0)],
        ['Other', """"Color" NOT LIKE '53790'""", QColor(230, 155, 240)]]

def rule_based_symbology(layer, renderer, label, expression, symbol, color):
    root_rule = renderer.rootRule()
    rule = root_rule.children()[0].clone()
    rule.setLabel(label)
    rule.setFilterExpression(expression)
    rule.symbol().setColor(QColor(color))
    root_rule.appendChild(rule)
    layer.setRenderer(renderer)
    layer.triggerRepaint()

for rule in rules:
    rule_based_symbology(layer, renderer, rule[0], rule[1], symbol, rule[2])

renderer.rootRule().removeChildAt(0)
iface.layerTreeView().refreshLayerSymbology(layer.id())

If you do not wish to see legend nodes for each color in the Table of Contents panel, just add these lines at the end:

legend_node = QgsProject().instance().layerTreeRoot().findLayer(layer.id())
legend_node.setExpanded(False)
| improve this answer | |
  • Thanks for the help! It works for the 2 rules you set up, however when I add more rules I get the error "TypeError: list indices must be integers or slices, not tuple". Any idea why that is? – gsae Jan 3 at 11:46
  • @gsae, My guess would be that you are missing a comma between two of the nested lists! See edits to my answer. – Ben W Jan 4 at 7:08
  • You're right, that was the problem. Thank you so much! – gsae Jan 6 at 9:06
  • You're welcome. If it solved your problem, it would be great if you could accept my answer. – Ben W Jan 6 at 9:13

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.