SuperAPI AI Directory

qgis-impl-print-layouts

Design & creation

View repository

Updated 10-15 22:18

About this skill

qgis-impl-print-layouts

Quick Reference

Layout Creation Workflow

Step Action Key Class
1. Create layout QgsPrintLayout(project) + initializeDefaults() QgsPrintLayout
2. Register layout layoutManager().addLayout(layout) QgsLayoutManager
3. Add map item QgsLayoutItemMap(layout) + set extent QgsLayoutItemMap
4. Add decorations Labels, legend, scale bar, north arrow Various QgsLayoutItem*
5. Configure export Set DPI, page size QgsLayoutExporter.*ExportSettings
6. Export exportToPdf(), exportToImage(), exportToSvg() QgsLayoutExporter

Layout Item Types

Class Purpose Key Methods
QgsLayoutItemMap Map display zoomToExtent(), setScale(), setCrs()
QgsLayoutItemLabel Text labels setText(), adjustSizeToText()
QgsLayoutItemLegend Map legend setLinkedMap(), setAutoUpdateModel()
QgsLayoutItemScaleBar Scale indicator setLinkedMap(), setStyle(), applyDefaultSize()
QgsLayoutItemPicture Images/north arrows setPicturePath()
QgsLayoutItemAttributeTable Data tables setVectorLayer(), setMaximumNumberOfFeatures()
QgsLayoutItemPolygon Shape decorations setSymbol()

Export Result Codes

Code Constant Meaning
0 Success Export completed
1 Canceled Export was canceled
2 MemoryError Insufficient memory
3 FileError Cannot write to file path
4 PrintError Printing subsystem error
5 SvgLayerError SVG layer export failed
6 IteratorError Atlas iterator failed

Critical Warnings

NEVER export a layout without setting the map item extent first -- the export produces a blank or incorrect map. ALWAYS call zoomToExtent() or setScale() on every QgsLayoutItemMap before exporting.

NEVER skip initializeDefaults() after creating a new QgsPrintLayout -- without it the layout has no pages and export fails silently.

NEVER forget to call layout.addLayoutItem(item) after creating a layout item -- items created without being added to the layout do not appear in exports.

ALWAYS register the layout with layoutManager().addLayout(layout) if you need it to persist in the project file.

ALWAYS check the export result code -- a return value other than QgsLayoutExporter.Success (0) indicates export failure.

NEVER call atlas.next() without calling atlas.beginRender() first -- the atlas iterator is not initialized until beginRender() is called.


Decision Tree: Which Export Method?

Need to export a map?
├── Single layout → use QgsLayoutExporter instance methods
│   ├── Need vector output? → exportToSvg()
│   ├── Need raster image? → exportToImage() (PNG, JPEG, TIFF)
│   └── Need print-ready document? → exportToPdf()
├── Multiple pages per feature? → Atlas generation
│   ├── Separate files per feature? → QgsLayoutExporter.exportToPdfs() (static)
│   └── Single multi-page PDF? → QgsLayoutExporter.exportToPdf() (static, with atlas)
└── Programmatic batch? → Loop with atlas.beginRender() / atlas.next() / atlas.endRender()

Essential Patterns

Pattern 1: Complete Layout Creation

from qgis.core import (
    QgsPrintLayout, QgsProject, QgsLayoutItemMap,
    QgsLayoutItemLabel, QgsLayoutItemLegend,
    QgsLayoutItemScaleBar, QgsLayoutSize,
    QgsLayoutPoint, QgsUnitTypes
)

project = QgsProject.instance()

# Step 1: Create and initialize layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()  # REQUIRED: creates default A4 page
layout.setName("My Map Layout")

# Step 2: Register with project
manager = project.layoutManager()
manager.addLayout(layout)

# Step 3: Add map item -- ALWAYS set extent
map_item = QgsLayoutItemMap(layout)
map_item.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters))
map_item.attemptMove(QgsLayoutPoint(10, 10, QgsUnitTypes.LayoutMillimeters))
map_item.zoomToExtent(project.mapLayersByName("my_layer")[0].extent())
layout.addLayoutItem(map_item)

# Step 4: Add title label
title = QgsLayoutItemLabel(layout)
title.setText("Map Title")
title.adjustSizeToText()
title.attemptMove(QgsLayoutPoint(10, 5, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title)

# Step 5: Add legend linked to map
legend = QgsLayoutItemLegend(layout)
legend.setLinkedMap(map_item)
legend.attemptMove(QgsLayoutPoint(220, 10, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend)

# Step 6: Add scale bar linked to map
scalebar = QgsLayoutItemScaleBar(layout)
scalebar.setLinkedMap(map_item)
scalebar.setStyle("Single Box")
scalebar.applyDefaultSize()
scalebar.attemptMove(QgsLayoutPoint(10, 170, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(scalebar)

Pattern 2: Export to PDF

from qgis.core import QgsLayoutExporter

exporter = QgsLayoutExporter(layout)

pdf_settings = QgsLayoutExporter.PdfExportSettings()
pdf_settings.dpi = 300

result = exporter.exportToPdf("/path/to/output.pdf", pdf_settings)
if result != QgsLayoutExporter.Success:
    raise RuntimeError(f"PDF export failed with code: {result}")

Pattern 3: Export to Image (PNG/JPEG/TIFF)

exporter = QgsLayoutExporter(layout)

img_settings = QgsLayoutExporter.ImageExportSettings()
img_settings.dpi = 300

result = exporter.exportToImage("/path/to/output.png", img_settings)
if result != QgsLayoutExporter.Success:
    raise RuntimeError(f"Image export failed with code: {result}")

Pattern 4: Export to SVG

exporter = QgsLayoutExporter(layout)

svg_settings = QgsLayoutExporter.SvgExportSettings()
svg_settings.dpi = 300

result = exporter.exportToSvg("/path/to/output.svg", svg_settings)
if result != QgsLayoutExporter.Success:
    raise RuntimeError(f"SVG export failed with code: {result}")

Pattern 5: Atlas Generation

atlas = layout.atlas()
atlas.setCoverageLayer(coverage_layer)
atlas.setEnabled(True)
atlas.setFilenameExpression("'output_' || @atlas_featurenumber")

# Export each atlas page to separate PDFs
pdf_settings = QgsLayoutExporter.PdfExportSettings()
pdf_settings.dpi = 300
result = QgsLayoutExporter.exportToPdfs(
    atlas, "/path/to/atlas_output/", pdf_settings
)
if result != QgsLayoutExporter.Success:
    raise RuntimeError(f"Atlas export failed with code: {result}")

Pattern 6: Atlas with Feature Filtering

atlas = layout.atlas()
atlas.setCoverageLayer(coverage_layer)
atlas.setEnabled(True)
atlas.setFilterFeatures(True)
atlas.setFilterExpression("\"type\" = 'residential'")
atlas.setFilenameExpression("\"name\" || '_map'")

Pattern 7: Manual Atlas Iteration

atlas = layout.atlas()
atlas.setCoverageLayer(coverage_layer)
atlas.setEnabled(True)

exporter = QgsLayoutExporter(layout)
pdf_settings = QgsLayoutExporter.PdfExportSettings()
pdf_settings.dpi = 300

atlas.beginRender()  # REQUIRED before iterating
while atlas.next():
    feature_num = atlas.currentFeatureNumber()
    page_name = atlas.nameForPage(feature_num)
    output_path = f"/path/to/output_{page_name}.pdf"
    exporter.exportToPdf(output_path, pdf_settings)
atlas.endRender()  # ALWAYS call to clean up

Common Operations

Page Setup

from qgis.core import QgsLayoutSize, QgsLayoutItemPage, QgsUnitTypes

# Change existing page size to A3 landscape
page = layout.pageCollection().page(0)
page.setPageSize(QgsLayoutSize(420, 297, QgsUnitTypes.LayoutMillimeters))

# Add a second page
new_page = QgsLayoutItemPage(layout)
new_page.setPageSize(QgsLayoutSize(297, 210, QgsUnitTypes.LayoutMillimeters))
layout.pageCollection().addPage(new_page)

Map Item: Set Scale and CRS

from qgis.core import QgsCoordinateReferenceSystem

map_item.setScale(50000)  # 1:50000
map_item.setCrs(QgsCoordinateReferenceSystem("EPSG:3857"))

Map Item: Grid Overlay

from qgis.core import QgsLayoutItemMapGrid

grid = QgsLayoutItemMapGrid("Main Grid", map_item)
grid.setIntervalX(1000)
grid.setIntervalY(1000)
grid.setAnnotationEnabled(True)
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra)
map_item.grids().addGrid(grid)

Add North Arrow (Picture Item)

from qgis.core import QgsLayoutItemPicture

picture = QgsLayoutItemPicture(layout)
picture.setPicturePath("/path/to/north_arrow.svg")
picture.attemptResize(QgsLayoutSize(20, 20, QgsUnitTypes.LayoutMillimeters))
picture.attemptMove(QgsLayoutPoint(250, 10, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(picture)

Attribute Table in Layout

from qgis.core import QgsLayoutItemAttributeTable, QgsLayoutFrame

table = QgsLayoutItemAttributeTable.create(layout)
table.setVectorLayer(layer)
table.setMaximumNumberOfFeatures(20)

frame = QgsLayoutFrame(layout, table)
frame.attemptResize(QgsLayoutSize(200, 100, QgsUnitTypes.LayoutMillimeters))
frame.attemptMove(QgsLayoutPoint(10, 200, QgsUnitTypes.LayoutMillimeters))
table.addFrame(frame)
layout.addMultiFrame(table)

Expression-Based Labels

label = QgsLayoutItemLabel(layout)
# Use QGIS expressions inside [% %] delimiters
label.setText("[% @project_title %] - Scale 1:[% @map_scale %]")
label.attemptMove(QgsLayoutPoint(10, 5, QgsUnitTypes.LayoutMillimeters))
label.adjustSizeToText()
layout.addLayoutItem(label)

Layout Manager Operations

manager = QgsProject.instance().layoutManager()

# List all layouts
for l in manager.printLayouts():
    print(l.name())

# Get layout by name
my_layout = manager.layoutByName("My Layout")

# Remove layout
manager.removeLayout(layout)

Template Save/Load

from qgis.core import QgsReadWriteContext
from qgis.PyQt.QtXml import QDomDocument

# Save layout as .qpt template
doc = QDomDocument()
layout.writeXml(doc, QgsReadWriteContext())
with open("/path/to/template.qpt", "w") as f:
    f.write(doc.toString())

# Load layout from .qpt template
with open("/path/to/template.qpt", "r") as f:
    content = f.read()
doc = QDomDocument()
doc.setContent(content)

new_layout = QgsPrintLayout(project)
new_layout.readXml(doc.documentElement(), doc, QgsReadWriteContext())
new_layout.setName("From Template")
manager.addLayout(new_layout)

Shape Decorations (Polygon/Polyline)

from qgis.core import QgsLayoutItemPolygon, QgsFillSymbol
from qgis.PyQt.QtCore import QPointF
from qgis.PyQt.QtGui import QPolygonF

polygon = QgsLayoutItemPolygon(
    QPolygonF([QPointF(0, 0), QPointF(100, 0), QPointF(100, 50), QPointF(0, 50)]),
    layout
)
props = {
    'color': '0,0,0,0',
    'style': 'no',
    'outline_color': 'black',
    'outline_width': '0.5'
}
symbol = QgsFillSymbol.createSimple(props)
polygon.setSymbol(symbol)
layout.addLayoutItem(polygon)

Common Positioning Methods (All Layout Items)

Method Purpose
attemptMove(QgsLayoutPoint) Set position on page
attemptResize(QgsLayoutSize) Set item dimensions
setFrameEnabled(bool) Toggle border frame
setBackgroundEnabled(bool) Toggle background fill
setLocked(bool) Prevent accidental edits
setReferencePoint(point) Set anchor point for positioning

Reference Links

Official Sources