Bug report #19311
setCrs() works incorrectly during Python plugin loading
Status: | Open | ||
---|---|---|---|
Priority: | Normal | ||
Assignee: | - | ||
Category: | Python plugins | ||
Affected QGIS version: | 3.2 | Regression?: | No |
Operating System: | Windows 7 x64 | Easy fix?: | No |
Pull Request or Patch supplied: | No | Resolution: | |
Crashes QGIS or corrupts data: | No | Copied to github as #: | 27139 |
Description
I have this code at the end of plugin loading (Python 3.6):
for data_dict in __DATA:
....
vlayer = QgsVectorLayer(uri.uri(), _v_layer0, _v_layer1)
QgsProject.instance().addMapLayer(vlayer)
QgsMapCanvas().setExtent(vlayer.extent())
QgsMapCanvas().setLayers([vlayer])
....
crs_dest = QgsCoordinateReferenceSystem(3857, QgsCoordinateReferenceSystem.PostgisCrsId)
QgsProject.instance().setCrs(crs_dest)
The destination CS is not set in QgsMapCanvas after that.
But QgsProject.instance().crs() shows correct CRS number at this moment (just after setCrs() ).
If this code is run in thread, setCrs() works in some situations.
Setting the CRS manually (by button, etc.) after loading also works.
I think <QGis> changes some QgsMapSettings after plugin loading and resets CRS settings.
In 2.18 version similar code (based on mapRenderer) worked here.
What should I do to run setCrs() at the start of plugin automatically?
History
#1 Updated by Igor Evdokimov over 6 years ago
I found that finally (after plugin loading) QGis sets Project CRS to the source CRS of loaded layers.
Maybe it's because constructor
QgsLayerTreeMapCanvasBridge::QgsLayerTreeMapCanvasBridge(...)
makes mAutoSetupOnFirstLayer(true) by default,
and then in QgsLayerTreeMapCanvasBridge::setCanvasLayers()
the call of QgsProject::instance()->setCrs( mFirstCRS ) sets layer's CRS to all Project?
#2 Updated by Igor Evdokimov over 6 years ago
Found solution/workaround:
https://gis.stackexchange.com/questions/273252/qgis-changing-canvas-crs-defaults-to-imported-layer
My working code:
from PyQt5.QtWidgets import QApplication
...
for data_dict in __DATA:
....
vlayer = QgsVectorLayer(uri.uri(), _v_layer0, _v_layer1)
QgsProject.instance().addMapLayer(vlayer)
QgsMapCanvas().setExtent(vlayer.extent())
QgsMapCanvas().setLayers([vlayer])
....
QApplication.instance().processEvents() #this operation solves this problem
crs_dest = QgsCoordinateReferenceSystem(3857, QgsCoordinateReferenceSystem.PostgisCrsId)
QgsProject.instance().setCrs(crs_dest)
Is it a bug nevertheless?
#3 Updated by Nyall Dawson over 6 years ago
QApplication.instance().processEvents()
^ is VERY dangerous to call, especially in places like this. It'll likely result in crashes.
What's the use case here? Why are you forcing a particular crs on startup?
#4 Updated by Igor Evdokimov over 6 years ago
Layers data are in 4236 crs, we need to set 3857 destination crs on startup.
#5 Updated by Matthew Baker over 6 years ago
All our source PostGIS data is stored in SRID:4326.
We make all our maps in State Plane SRID:2877
This feature is handy so that every time we start a map in QGIS, we don't have to set the 'on the fly' reprojection, and takes the guesswork out for new users who don't know about coordinate systems and get them going with a good looking map right away.
Nyall Dawson wrote:
QApplication.instance().processEvents()
^ is VERY dangerous to call, especially in places like this. It'll likely result in crashes.
What's the use case here? Why are you forcing a particular crs on startup?