2

I load into a PostGIS database, 2 shapefiles of the QGIS sample data :

  • alaska.shp
  • storagep.shp

with the shell code :

shp2pgsql -s 2964 storagep.shp public.storagep > storagep.sql
shp2pgsql -s 2964 alaska.shp public.alaska > alaska.sql
psql -h localhost -U postgres -d postgres -f storagep.sql
psql -h localhost -U postgres -d postgres -f alaska.sql

Under QGIS 3.6.1, I execute in a new project the following code in the QGIS Python editor :

def loadPgLayer(instance, vl, path, name, data_filter=""):
    """load a postgis vector layer"""
    vl.setDataSource(path, name, "postgres")
    if vl.isValid() and vl.setSubsetString(data_filter):
        instance.addMapLayer(vl)

canvas = iface.mapCanvas()
instance = QgsProject.instance()

uri = QgsDataSourceUri()
uri_params = dict(aHost="127.0.0.1",
                  aPort="5432",
                  aDatabase="postgres",
                  aUsername="postgres",
                  aPassword="")
uri.setConnection(**uri_params)

vl_alaska = QgsVectorLayer()
vl_storagep = QgsVectorLayer()

name = "alaska"
uri.setDataSource("public", name, "geom")
path = uri.uri(False)
loadPgLayer(instance, vl_alaska, path, name)

name = "storagep"
uri.setDataSource("public", name, "geom")
path = uri.uri(False)
loadPgLayer(instance, vl_storagep, path, name)

# set the project crs
instance.setCrs(QgsCoordinateReferenceSystem(2964))
# zoom on vl_storagep extent
rect = canvas.mapSettings().layerExtentToOutputExtent(vl_storagep, vl_storagep.extent())
canvas.setExtent(rect)
# for update view
canvas.refresh()

This code load the two PostGIS vector layers but doesn't zoom on the extents of vl_storagep layer.

But, after executing this code above, in the QGIS Python console I enter this piece of code below again :

canvas.setExtent(rect)
# for update view
canvas.refresh()

and it zooms on the desired extents.

If I try this kind of code with Shapefiles Vector Layers, everything is good, but as soon as it's PostGIS Vector Layers, this malfunction (?) appears.

For information :

  • OS : Ubuntu 18.04
  • QGIS : 3.6.1
  • PostGIS :
SELECT postgis_version();
--> 2.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
4
  • Could you please clarify what the issue is? You said your initial code does not zoom to the extent of the PostGIS layers but when adding an extra line canvas.refresh(), it solves your problem?
    – Joseph
    Apr 16, 2019 at 14:19
  • I've edit my post. The canvas.refresh() code is here just for map's aesthetic. I execute a first time the whole PyQGIS code and after, in the console, just with canvas.setExtent(rect) (as objects are still in memory), it zoom at the right extent. But I don't achieve this in one go. Apr 16, 2019 at 14:29
  • Before you define rect, try adding vl_storagep = QgsProject.instance().mapLayersByName('storagep')[0] so that you're defining vl_storagep again but as a full PostGIS layer and not an empty QgsVectorLayer() object.
    – Joseph
    Apr 16, 2019 at 15:33
  • Thank you but it doesn't work. I don't think it's related to the vector layer because another code like canvas.zoomScale(10000) instead of canvas.setExtent(rect) doesn't work too. It seams like QGIS, after loading PostGIS layers, update canvas extents with the extent of all layers. Apr 16, 2019 at 15:41

1 Answer 1

4

you need refresh canvas and wait to finish render before setExtent.

canvas.refresh()
canvas.waitWhileRendering()

complet code sample

def loadPgLayer(instance, vl, path, name, data_filter=""):
    """load a postgis vector layer"""
    vl.setDataSource(path, name, "postgres")
    if vl.isValid() and vl.setSubsetString(data_filter):
        instance.addMapLayer(vl)

canvas = iface.mapCanvas()
instance = QgsProject.instance()

uri = QgsDataSourceUri()
uri_params = dict(aHost="127.0.0.1",
                  aPort="5433",
                  aDatabase="test",
                  aUsername="postgres",
                  aPassword="postgres")
uri.setConnection(**uri_params)

vl_alaska = QgsVectorLayer()
vl_storagep = QgsVectorLayer()

name = "alaska"
uri.setDataSource("public", name, "geom")
path = uri.uri(False)
loadPgLayer(instance, vl_alaska, path, name)

name = "storagep"
uri.setDataSource("public", name, "geom")
path = uri.uri(False)
loadPgLayer(instance, vl_storagep, path, name)

# set the project crs
instance.setCrs(QgsCoordinateReferenceSystem(2964))

canvas.refresh()
canvas.waitWhileRendering()

# zoom on vl_storagep extent
rect = canvas.mapSettings().layerExtentToOutputExtent(vl_storagep, vl_storagep.extent())
canvas.setExtent(rect)
# for update view
canvas.refresh()

enter image description here

1
  • 2
    It's exactly what I'm looking for, it's perfect. Thank you for this (and all your contributions for the QGIS project). Apr 17, 2019 at 7:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.