地图布局与打印
第十一章 地图布局与打印
11.1 打印布局概述
11.1.1 打印布局简介
打印布局(Print Layout)是QGIS中用于创建专业地图输出的工具,支持:
- 多种地图元素组合
- 自定义页面尺寸
- 高质量输出(PDF、图片、SVG)
- 地图册功能
11.1.2 创建打印布局
创建新布局:
项目 > 新建打印布局 (Ctrl+P)
输入布局名称
管理布局:
项目 > 布局管理器
11.2 布局界面
11.2.1 界面组成
┌─────────────────────────────────────────────────────────────────┐
│ 菜单栏和工具栏 │
├────────────────┬─────────────────────────────┬─────────────────┤
│ │ │ │
│ 元素面板 │ 画布区域 │ 属性面板 │
│ │ │ │
│ │ │ │
│ │ │ │
└────────────────┴─────────────────────────────┴─────────────────┘
11.2.2 工具栏
| 工具组 | 功能 |
|---|---|
| 导航工具 | 缩放、平移画布 |
| 添加元素 | 添加地图、图例、比例尺等 |
| 编辑工具 | 选择、移动、调整元素 |
| 对齐工具 | 元素对齐和分布 |
| 地图工具 | 地图内容交互 |
11.3 页面设置
11.3.1 页面属性
from qgis.core import QgsLayoutItemPage, QgsLayoutSize, QgsUnitTypes
layout = QgsProject.instance().layoutManager().layoutByName("MyLayout")
page = layout.pageCollection().page(0)
# 设置页面大小
page.setPageSize(QgsLayoutSize(297, 210, QgsUnitTypes.LayoutMillimeters)) # A4横向
# 或使用预设尺寸
page.setPageSize('A3', QgsLayoutItemPage.Landscape)
11.3.2 常用纸张尺寸
| 纸张 | 尺寸(mm) | 说明 |
|---|---|---|
| A0 | 841×1189 | 大幅面 |
| A1 | 594×841 | 大幅面 |
| A2 | 420×594 | 中幅面 |
| A3 | 297×420 | 中幅面 |
| A4 | 210×297 | 标准 |
| Letter | 216×279 | 美国标准 |
| Legal | 216×356 | 美国法律 |
11.3.3 多页布局
# 添加新页面
layout.pageCollection().addPage(QgsLayoutItemPage(layout))
# 设置新页面属性
new_page = layout.pageCollection().page(1)
new_page.setPageSize('A4', QgsLayoutItemPage.Portrait)
11.4 地图元素
11.4.1 添加地图
from qgis.core import QgsLayoutItemMap
# 创建地图元素
map_item = QgsLayoutItemMap(layout)
map_item.setRect(20, 20, 180, 180) # x, y, width, height (mm)
map_item.setExtent(iface.mapCanvas().extent())
layout.addLayoutItem(map_item)
11.4.2 地图设置
# 设置比例尺
map_item.setScale(50000)
# 锁定图层
map_item.setLayers([layer1, layer2])
map_item.setKeepLayerSet(True)
# 锁定样式
map_item.setKeepLayerStyles(True)
# 设置CRS
map_item.setCrs(QgsCoordinateReferenceSystem("EPSG:4326"))
# 设置旋转
map_item.setMapRotation(45)
11.4.3 地图网格
from qgis.core import QgsLayoutItemMapGrid
# 创建网格
grid = QgsLayoutItemMapGrid("Grid", map_item)
grid.setEnabled(True)
grid.setIntervalX(10000) # X间隔
grid.setIntervalY(10000) # Y间隔
grid.setStyle(QgsLayoutItemMapGrid.Solid)
# 网格标注
grid.setAnnotationEnabled(True)
grid.setAnnotationFormat(QgsLayoutItemMapGrid.DegreeMinuteSecond)
map_item.grids().addGrid(grid)
11.4.4 地图范围指示器
from qgis.core import QgsLayoutItemMapOverview
# 在主地图上显示概览图范围
overview = QgsLayoutItemMapOverview("Overview", map_item)
overview.setLinkedMap(overview_map)
overview.setFrameEnabled(True)
overview.setFrameStrokeColor(QColor(255, 0, 0))
map_item.overviews().addOverview(overview)
11.5 图例
11.5.1 添加图例
from qgis.core import QgsLayoutItemLegend
legend = QgsLayoutItemLegend(layout)
legend.setTitle("图例")
legend.setLinkedMap(map_item)
legend.attemptMove(QgsLayoutPoint(210, 20, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend)
11.5.2 图例设置
# 自动更新
legend.setAutoUpdateModel(True)
# 手动控制图层
legend.setAutoUpdateModel(False)
legend.model().setLayerSet([layer1, layer2])
# 分列
legend.setColumnCount(2)
# 样式设置
legend.setStyle(QgsLegendStyle.Title, style)
legend.setFontColor(QColor(0, 0, 0))
# 背景
legend.setBackgroundEnabled(True)
legend.setBackgroundColor(QColor(255, 255, 255))
11.5.3 图例项目
from qgis.core import QgsLegendRenderer
# 修改图例项目名称
model = legend.model()
root = model.rootGroup()
for child in root.children():
if child.name() == "old_name":
child.setName("新名称")
11.6 比例尺
11.6.1 添加比例尺
from qgis.core import QgsLayoutItemScaleBar
scalebar = QgsLayoutItemScaleBar(layout)
scalebar.setStyle('Single Box')
scalebar.setLinkedMap(map_item)
scalebar.setUnits(QgsUnitTypes.DistanceKilometers)
scalebar.setNumberOfSegments(4)
scalebar.setNumberOfSegmentsLeft(2)
scalebar.setUnitsPerSegment(10) # 每段10公里
layout.addLayoutItem(scalebar)
11.6.2 比例尺样式
可用样式:
- Single Box(单框)
- Double Box(双框)
- Line Ticks Middle(中间刻度线)
- Line Ticks Down(下刻度线)
- Line Ticks Up(上刻度线)
- Numeric(数字)
scalebar.setStyle('Double Box')
scalebar.setHeight(5) # 高度
scalebar.setLabelBarSpace(2) # 标注间距
11.7 指北针
11.7.1 添加指北针
from qgis.core import QgsLayoutItemPicture
north_arrow = QgsLayoutItemPicture(layout)
north_arrow.setPicturePath('/path/to/north_arrow.svg')
# 或使用内置图片
north_arrow.setPicturePath(':/images/north_arrows/layout_default_north_arrow.svg')
north_arrow.setLinkedMap(map_item)
north_arrow.attemptResize(QgsLayoutSize(20, 20, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(north_arrow)
11.7.2 内置指北针
QGIS提供多种内置指北针样式,位于:
资源路径: images/north_arrows/
11.8 文字元素
11.8.1 添加标签
from qgis.core import QgsLayoutItemLabel
label = QgsLayoutItemLabel(layout)
label.setText("地图标题")
label.setFont(QFont("Arial", 24, QFont.Bold))
label.adjustSizeToText()
layout.addLayoutItem(label)
11.8.2 HTML内容
label = QgsLayoutItemLabel(layout)
label.setMode(QgsLayoutItemLabel.ModeHtml)
label.setText('''
<h1 style="color: blue;">地图标题</h1>
<p>副标题说明文字</p>
''')
11.8.3 表达式
label = QgsLayoutItemLabel(layout)
label.setText('[% @project_title %]') # 项目标题
label.setText('[% format_date(now(), \'yyyy-MM-dd\') %]') # 日期
label.setText('[% @layout_name %]') # 布局名称
11.9 其他元素
11.9.1 图片
from qgis.core import QgsLayoutItemPicture
picture = QgsLayoutItemPicture(layout)
picture.setPicturePath('/path/to/logo.png')
picture.setResizeMode(QgsLayoutItemPicture.Zoom)
layout.addLayoutItem(picture)
11.9.2 形状
from qgis.core import QgsLayoutItemShape
# 矩形
rect = QgsLayoutItemShape(layout)
rect.setShapeType(QgsLayoutItemShape.Rectangle)
rect.attemptResize(QgsLayoutSize(50, 30, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(rect)
# 椭圆
ellipse = QgsLayoutItemShape(layout)
ellipse.setShapeType(QgsLayoutItemShape.Ellipse)
# 三角形
triangle = QgsLayoutItemShape(layout)
triangle.setShapeType(QgsLayoutItemShape.Triangle)
11.9.3 属性表
from qgis.core import QgsLayoutItemAttributeTable
table = QgsLayoutItemAttributeTable.create(layout)
table.setVectorLayer(layer)
table.setMaximumNumberOfFeatures(20)
table.setDisplayedFields(['name', 'population'])
# 添加到框架
frame = QgsLayoutFrame(layout, table)
table.addFrame(frame)
11.9.4 HTML框架
from qgis.core import QgsLayoutItemHtml
html = QgsLayoutItemHtml(layout)
html.setUrl('https://example.com')
# 或设置内容
html.setContentMode(QgsLayoutItemHtml.ManualHtml)
html.setHtml('<div>HTML内容</div>')
11.10 地图册
11.10.1 启用地图册
from qgis.core import QgsLayoutAtlas
atlas = layout.atlas()
atlas.setEnabled(True)
atlas.setCoverageLayer(coverage_layer)
atlas.setPageNameExpression('"name"')
11.10.2 地图册设置
# 设置要素过滤
atlas.setFilterFeatures(True)
atlas.setFilterExpression('"type" = \'city\'')
# 设置排序
atlas.setSortFeatures(True)
atlas.setSortExpression('"name"')
# 设置文件名
atlas.setFilenameExpression("'map_' || @atlas_featurenumber")
11.10.3 地图册表达式
地图册提供特殊表达式变量:
@atlas_feature- 当前要素@atlas_featureid- 要素ID@atlas_featurenumber- 序号@atlas_filename- 文件名@atlas_geometry- 几何@atlas_pagename- 页面名称@atlas_totalfeatures- 总数
label.setText('[%@atlas_featurenumber%] / [%@atlas_totalfeatures%]')
11.11 导出输出
11.11.1 导出为图片
from qgis.core import QgsLayoutExporter
exporter = QgsLayoutExporter(layout)
# 导出PNG
settings = QgsLayoutExporter.ImageExportSettings()
settings.dpi = 300
exporter.exportToImage('/path/to/output.png', settings)
# 导出其他格式
exporter.exportToImage('/path/to/output.jpg', settings)
exporter.exportToImage('/path/to/output.tif', settings)
11.11.2 导出为PDF
settings = QgsLayoutExporter.PdfExportSettings()
settings.dpi = 300
settings.rasterizeWholeImage = False
settings.forceVectorOutput = True
settings.exportMetadata = True
exporter.exportToPdf('/path/to/output.pdf', settings)
11.11.3 导出为SVG
settings = QgsLayoutExporter.SvgExportSettings()
settings.dpi = 300
settings.forceVectorOutput = True
exporter.exportToSvg('/path/to/output.svg', settings)
11.11.4 批量导出地图册
atlas = layout.atlas()
# 导出所有页面为图片
exporter.exportToImage('/path/to/atlas/', QgsLayoutExporter.ImageExportSettings())
# 导出为单个PDF
exporter.exportToPdf('/path/to/atlas.pdf', QgsLayoutExporter.PdfExportSettings())
# 导出为多个PDF
for i in range(atlas.count()):
atlas.seekTo(i)
exporter.exportToPdf(f'/path/to/page_{i}.pdf', settings)
11.12 模板管理
11.12.1 保存为模板
# 保存布局为模板
layout.saveAsTemplate('/path/to/template.qpt')
11.12.2 从模板创建
# 从模板创建布局
template_path = '/path/to/template.qpt'
with open(template_path) as f:
template_content = f.read()
doc = QDomDocument()
doc.setContent(template_content)
layout = QgsPrintLayout(QgsProject.instance())
layout.setName("New from Template")
layout.loadFromTemplate(doc, QgsReadWriteContext())
QgsProject.instance().layoutManager().addLayout(layout)
11.13 小结
本章详细介绍了QGIS打印布局功能:
关键要点:
- 掌握打印布局的创建和管理
- 了解各种地图元素的添加和配置
- 熟练使用图例、比例尺、指北针等
- 掌握地图册功能批量出图
- 了解各种导出格式和设置
打印布局是制作专业地图产品的关键工具。
上一章:第10章 空间分析工具
下一章:第12章 数据编辑与数字化

浙公网安备 33010602011771号