QGIS PyQGIS – setExtent() and attemptResize() Methods in Print Layout Items

pyqgispyqgis-3pythonqgisqgis-3

I'm trying to arrange some map items onto a print layout. Let's start with the map item itself.

Here is my code to add a map item to the print layout. Specifically I have questions about the setExtent() and attemptResize() functions.

In this code below I set the extent with setExtent() before setting the size with attemptResize()

#This creates a new print layout
project = QgsProject.instance()                    
manager = project.layoutManager()
layout = QgsPrintLayout(project)
layout.initializeDefaults()                         
layout.setName('My Layout')                           
manager.addLayout(layout) 

#This is where I configure layout items
map = QgsLayoutItemMap(layout)
rectangle = QgsRectangle(-1350312, -21811, 1741463, 116086) #These are coordinates around my desired map extent
map.setExtent(rectangle)

map.attemptResize(QgsLayoutSize(250, 180, QgsUnitTypes.LayoutMillimeters))

#adds map to print layout
layout.addLayoutItem(map)

This produces the following Print Layout. Notice that the map is "rendering" (Why????). But the sizing of the item is what I want. If I try to export this as a .pdf or image, the final product is blank.
enter image description here

According to this thread, I need to set the map item size before I set the extent. Here is the code, where I have simply switched the order of setExtent() and attemptResize():

#This creates a new print layout
project = QgsProject.instance()                    
manager = project.layoutManager()
layout = QgsPrintLayout(project)
layout.initializeDefaults()                         
layout.setName('My Layout11')                           
manager.addLayout(layout) 

map = QgsLayoutItemMap(layout)

map.attemptResize(QgsLayoutSize(250, 180, QgsUnitTypes.LayoutMillimeters)) 

rectangle = QgsRectangle(-1350312, -21811, 1741463, 116086)
map.setExtent(rectangle)
layout.addLayoutItem(map)

and I get the following print layout. If I zoom in closely, the extent is still correct. But as you can see the image is very small and I have no idea what the attemptResize() function is even doing here, as the units of where the object is on the canvas makes no sense:
enter image description here

What am I not understanding correctly??

Best Answer

The order of when you set the extent, add the map to the layout, and resize the rectangle is important. Steps to add a map to a new layout in QGIS 3.

  • Instantiate the map object with QgsLayoutItemMap(layout)
    • Set a base Rectangle
    • Set the extent
    • Add the map to the layout object, layout.addLayoutItem(map)
  • Now you can Move & Resize the rectangle as precise as you want

# Project, Manager, & PrintLayout Classes
project = QgsProject.instance()
manager = project.layoutManager()
layout = QgsPrintLayout(project)
layout.initializeDefaults()
layout.setName('gis-stackexchange-309219')
manager.addLayout(layout)

# Map
#   Defaults of `A4`, `Landscape`, & `LayoutMillimeters` are 
#   due to `layout.initializeDefaults()`
map = QgsLayoutItemMap(layout)
map.setRect(QRectF(20, 20, 200, 100))  # The Rectangle will be overridden below

# Extent
rectangle = QgsRectangle(-1350312, -21811, 1741463, 116086)
map.setExtent(rectangle)
layout.addLayoutItem(map)

# Move & Resize
#   Demo of map origin and map size in mixed units
map.attemptMove(QgsLayoutPoint(0.25, 0.25, QgsUnitTypes.LayoutInches))
map.attemptResize(QgsLayoutSize(250,  200, QgsUnitTypes.LayoutMillimeters))

The source code for the QGIS Plugin Quick Print shows how they did printing in QGIS. https://github.com/MarcoDuiker/QGIS_QuickPrint/blob/d1c946a7b6187553c92ffad7a0cc23d39a1bc593/quick_print3.py#L299


enter image description here

Related Question