QGIS – Difference Between iface.mapCanvas and QgsMapCanvas

pyqgisqgisstandalone

I am working on standalone pyqgis script and I wanted to set project extent to position on imported layer.
First I tried with:

vlayer = QgsVectorLayer("data/layers/layer1.gpkg", "layer_name", "ogr")
canvas= iface.mapCanvas()
canvas.setExtent(layer.extent())
canvas.refresh()

And I got: AttributeError: 'NoneType' object has no attribute 'mapCanvas'

Then I tried with using the same layer:

ex = vlayer.extent()
canvas = QgsMapCanvas()
canvas.setExtent(ex)

And then it worked.
I am wondering why i could do this using QgsMapCanvas and not using mapCanvas from iface(which i imported from qgis.utils import iface).

What is the difference between these two object?
Is it meant to be like this because someone would want to work with native Qgis and someone with standalone app or something else?

Best Answer

On the one hand, QgsMapCanvas is a class. You can always create new canvas objects from it (as you did already in your second attempt).

On the other hand, iface.mapCanvas() is an instance, an object of the class QgsMapCanvas. iface.mapCanvas() is initialized when you load QGIS app with GUI (Python should be enabled to use it), and refers to the main canvas you see in QGIS GUI.

In a standalone app, iface is not initialized. QGIS app has no default canvas, and you are responsible for adding one to your app (which is optional, as you can have an app with no canvas). That's why you cannot call iface.mapCanvas() when working on a standalone app.

Related Question