7

Refreshing the map extent on QGIS's composer requires to click on Set map extent to match main canvas extent enter image description here

I was wondering if there was a possibility to have a map extent (in the composer) that constantly refreshes itself depending on the main canvas location. That means, that no manual action has to be done.

In comparison to ArcGIS and if I'm not mistaken, the solution is symbolised by a locker located right bottom corner (at least for ArcMap 10).

Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
Remi.M
  • 119
  • 6
  • I don't think there is the option, however someone might know more than me – JonasV Oct 14 '20 at 13:12
  • Based on this answer you should be able to use data defined override on the extent of your map element. Please let us know, if you were able to achieve your desired result. – Erik Oct 14 '20 at 13:31

2 Answers2

4

I think the main issue here is, that there is no option to set the auto-refresh rate of print-layout-maps (at least none that I know of). So you can use data defined override for your extents as below, but the print-layout-canvas will only refresh if you manually click on the refresh button, minimize and remaximize the print layout window, or something like that. Which makes it a little bit pointless... But in my eyes this would be a nice feature though.

However, you could create a custom function like the following:

@qgsfunction(args='auto', group='Custom')
def my_canvas(feature, parent):    
    e = QgsGeometry.fromWkt(qgis.utils.iface.mapCanvas().extent().asWktPolygon())
    return e

It returns the geometry of your current main-window-map-canvas. You can then use x_max(my_canvas()), x_min(my_canvas()), y_min(my_canvas()), y_max(my_canvas()) as expressions for data defined override for your print-layout-map properties:

enter image description here

PS: I am not an expert in PyQGIS, so I dont know why I had to use .asWktPolygon() as step inbetween. It just failed returning QgsGeometry() directly when using .asPolygon().

Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
MrXsquared
  • 34,292
  • 21
  • 67
  • 117
1

Thank you for those first answers. As I have poor knowledge of coding, it'll take time before I meet a result.

My research led me to a plugin (Layout loader), which is able when opening the composer to zoom directly to the canvas location. However, for certain reasons, I am not likely to use that plugin, and so I'll carry on with your solutions.

Here is the link to the plugin : link to Github

And here, an extract of the code:

# Get current canvas extend and apply that to all maps (items) in layout
# Replace any text "{{title}}" in any layout label with the dialog Title text
canvas = iface.mapCanvas()
for item in l.items():
    if item.type()==65639: # Map
        item.zoomToExtent(canvas.extent())
    if item.type()==65641: # Label
        item.setText(item.text().replace('{{title}}', title_text))
Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
Remi.M
  • 119
  • 6