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??

4
+50

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

  • First, thank you for the explanation. This is far better than anything else I have been able to find in the documentation or in other StackOverflow threads. Did you figure this out yourself of did you reference it from somewhere else? Also, can you say anything more about setRect()? If it is getting overwritten, why do we set it in the first place? Also, after experimenting, I see as long as setRect() is called, the arguments (ints) for QrectF(int, int, int, int) don't really seem to do anything. Why? – Erich Purpur Jan 24 at 16:18
  • 1
    Added a link to the QGIS Quick Print source code. That project was useful in understanding a basis of how to automate QGIS Print Layout in Python. Stack also helped immensely. I agree, calling setRect() know we are going to arrive doesn't feel right, but without the initial setRect() it seemed to fail. – RobLabs Jan 25 at 0:38
  • I was not aware of QuickPrint. This is great, thanks again! – Erich Purpur Jan 25 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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