So far, we have loaded vector layers, looked at their attributes, and filtered features based on these attributes. Now it’s time to look into how to change a vector layer’s style.

The following example assumes that you have loaded a point vector layer:

uri = "E:/Geodata/NaturalEarth/vector_v4/natural_earth_vector.gpkg_v4.1.0/packages/natural_earth_vector.gpkg|layername=ne_110m_populated_places_simple"
vlayer = iface.addVectorLayer(uri, "places", "ogr")

By default, QGIS displays points as randomly colored circles. Let’s see how we can alter the symbology!

First, let’s make the circles bigger:


Don’t forget to call triggerRepaint()! Otherwise you won’t see the changes taking effect.

Nice! Let’s take one step back and examine the code:

vlayer.renderer() gives us access to the vector layers renderer object. There are different types of renderers. As a QGIS user you know them as Single Symbol (QgsSingleSymbolRenderer), Categorized (QgsCategorizedSymbolRenderer), Graduated (QgsGraduatedSymbolRenderer), and so on.

By default, vector layers are assigned single symbol renderers. These renderers have a single symbol that we can access using the symbol() function.

Now that we have access to the symbol, we can change its size using the setSize() function, providing it a numeric value for the desired size.

Similarly, we can change the symbol’s color using setColor():


The setColor() function expects a QColor object as its parameter. This is why we create a new QColor object using QColor(“blue”). (There are many other ways to create a QColor object which you can find in the official Qt documentation.)

Finally, let’s get rid of those boring circles and have stars instead:


Note how we are not calling symbol().setShape() but symbol().symbolLayer(0).setShape()! This is because each symbol can consist of multiple symbol layers but by default it has only one. We can access this first (and only) symbol layer using symbolLayer(0). The symbol layer is the right place to change the shape of the marker using setShape(). Available shapes (based on QgsSimpleMarkerSymbolLayerBase) include: Arrow, ArrowHead, ArrowHeadFilled, Circle, Cross, Cross2, CrossFill, DiagonalHalfSquare, Diamond, EquilateralTriangle, HalfSquare, Hexagon, LeftHalfTriangle, Line, Pentagon, QuarterCircle, QuarterSquare, RightHalfTriangle, SemiCircle, Square, Star, ThirdCircle, and Triangle.

Finally, you might have noticed that the symbol in the layer list (right next to the layer name) has not been updated. To fix this, we need to call the correct refresh function:


The refreshLayerSymbology() function needs to know which layer’s symbology should be refreshed. That’s why we need to provide it with our vector layer’s id.

These are the basics of vector styling using a single symbol renderer with a symbol consisting of one symbol layer.


PyQGIS 101 is a work in progress. I’d appreciate any feedback, particularly from beginners!

  1. Thanks a lot for this, I tried playing with this too, what I tried to do was get my Openstreetmap edits with overpass, convert everything to points, and style my points with a heatmap. I found the function that would control it but didn’t manage to get it working. Would you be interested to do an example of this? Thanks again

    • Thank you for your feedback! I’ll look into the heatmap renderer and see what I can do.

      • Looks like this does the trick:

  2. Neil Falconer said:

    Thank you for these tutorial, greatly appreciated!! Very useful to get familiar with the various objects and their properties and functions/methods.

  3. Kurt said:

    thank you very much for this really nice intro into PyQGIS, hope there are coming more samples…

  4. Mohab said:

    so far this is the last tut, thank you for the simple intro to PyQGIS, you ‘ve reached a global appreciation as i’m far remote from you and very thankful for this nice intro…keep up!

  5. Kathinka Bradley said:

    Thank you very much for this easy to follow and well written tutorial! I learnt a great deal already.
    Sadly, I ran into an error I can’t figure out. I used the layers you suggested earlier and QGIS 2.18.3 and wrote the following:
    uri = “C:/someadress/” #here I used my adress for the layer
    vlayer = iface.addVectorLayer(uri, “places”, “ogr”)
    Nothing changed though, the sizes, colours and shapes stayed the same. But the following error occured: “”AttributeError: ‘QgsVectorLayer’ object has no attribute ‘setShape”. I can’t figure out what I did wrong, pretty sure it was just a minor mistake, though.

    Could you please help me?

    • Dear Kathinka,
      This tutorial is written for QGIS 3. There are slight differences between the QGIS 2 and QGIS 3 Python APIs. For QGIS 2, you need:

      If you want to follow this tutorial, please upgrade to QGIS 3.

      • Kathinka Bradley said:

        Okay, thank you very much!
        I just started working with QGIS a few months ago and wanted to get used to the old version first, a mistake I guess.

      • Either version is good but you’ll need to be careful which version the documentation is written for, particularly when it comes to the Python API.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: