De codesnippers op deze pagina hebben de volgende import nodig:
1import os
2
3from qgis.core import (
4 QgsGeometry,
5 QgsMapSettings,
6 QgsPrintLayout,
7 QgsMapSettings,
8 QgsMapRendererParallelJob,
9 QgsLayoutItemLabel,
10 QgsLayoutItemLegend,
11 QgsLayoutItemMap,
12 QgsLayoutItemPolygon,
13 QgsLayoutItemScaleBar,
14 QgsLayoutExporter,
15 QgsLayoutItem,
16 QgsLayoutPoint,
17 QgsLayoutSize,
18 QgsUnitTypes,
19 QgsProject,
20 QgsFillSymbol,
21)
22
23from qgis.PyQt.QtGui import (
24 QPolygonF,
25 QColor,
26)
27
28from qgis.PyQt.QtCore import (
29 QPointF,
30 QRectF,
31 QSize,
32)
10. Kaart renderen en afdrukken
Er zijn over het algemeen twee benaderingen wanneer ingevoerde gegevens zouden moeten worden gerenderd als een kaart: ofwel doe het op de snelle manier met behulp van QgsMapRendererJob of produceer een meer fijn afgestemde uitvoer door de kaart samen te stellen met behulp van de klasse QgsLayout
.
10.1. Eenvoudig renderen
Het renderen wordt gedaan door een object QgsMapSettings
te maken om de instellingen voor renderen te definiëren, en dan een QgsMapRendererJob
te construeren met deze instellingen. Het laatste wordt dan gebruikt om de resulterende afbeelding te maken.
Hier is een voorbeeld:
1image_location = os.path.join(QgsProject.instance().homePath(), "render.png")
2
3vlayer = iface.activeLayer()
4settings = QgsMapSettings()
5settings.setLayers([vlayer])
6settings.setBackgroundColor(QColor(255, 255, 255))
7settings.setOutputSize(QSize(800, 600))
8settings.setExtent(vlayer.extent())
9
10render = QgsMapRendererParallelJob(settings)
11
12def finished():
13 img = render.renderedImage()
14 # save the image; e.g. img.save("/Users/myuser/render.png","png")
15 img.save(image_location, "png")
16
17render.finished.connect(finished)
18
19# Start the rendering
20render.start()
21
22# The following loop is not normally required, we
23# are using it here because this is a standalone example.
24from qgis.PyQt.QtCore import QEventLoop
25loop = QEventLoop()
26render.finished.connect(loop.quit)
27loop.exec_()
10.2. Lagen met een verschillend CRS renderen
Als u meer dan één laag hebt en zij hebben een verschillend CRS, zal het eenvoudige voorbeeld hierboven niet werken: om de juiste waarden uit de berekeningen van het bereik te krijgen dient u expliciet het doel-CRS in te stellen.
layers = [iface.activeLayer()]
settings.setLayers(layers)
settings.setDestinationCrs(layers[0].crs())
10.3. Uitvoer door Afdruklay-out te gebruiken
Afdruklay-out is een zeer handig gereedschap als u een uitgebreidere uitvoer wilt dan de eenvoudige rendering van die welke hierboven is weergegeven. Het is mogelijk complexe lay-outs voor kaarten te maken, bestaande uit weergaven van kaarten, labels, legenda, tabellen en andere elementen die gewoonlijk aanwezig zijn op papieren kaarten. De lay-outs kunnen dan worden geëxporteerd naar PDF, rasterafbeeldingen of direct worden afgedrukt op een printer.
De lay-out bestaat uit een aantal klassen. Zij maken allemaal deel uit van de bronbibliotheek. De toepassing QGIS heeft een handige gebruikersinterface voor de plaatsing van de elementen, hoewel die niet beschikbaar is in de bibliotheek van de gebruikersinterface. Als u nog niet bekend bent met Qt Graphics View framework, wordt u aangeraden om nu de documentatie te bekijken, omdat de lay-out daarop is gebaseerd.
De centrale klasse van de afdruklay-out is de klasse QgsLayout
die is afgeleid van de klasse voor Qt QGraphicsScene. Laten we er een instantie van maken:
project = QgsProject.instance()
layout = QgsPrintLayout(project)
layout.initializeDefaults()
Dit initialiseert de lay-out met enkele standaard instellingen, in het bijzonder een lege pagina A4 aan de lay-out. U kunt lay-outs maken zonder de methode initializeDefaults()
aan te roepen, maar u dient zelf het toevoegen van pagina’s aan de lay-out te regelen.
De vorige code maakt een “tijdelijke” lay-out die niet zichtbaar is in de GUI. Het kan handig zijn om bijvoorbeeld snel enkele items toe te voegen en te exporteren, zonder het project aan te passen of deze wijzigingen aan de gebruiker te laten zien. Als u de lay-out wilt opslaan/herstellen naast het project en beschikbaar zijn in Lay-out beheren, voeg dan toe:
layout.setName("MyLayout")
project.layoutManager().addLayout(layout)
Nu kunnen we verschillende elementen (kaart, label, …) toevoegen aan de lay-out. Al deze objecten worden weergegeven door klassen die erven van de basisklasse QgsLayoutItem
.
Hier is een beschrijving van enkele van de belangrijkste items voor lay-out die aan een lay-out kunnen worden toegevoegd.
map — Hier maken we een kaart van een aangepaste grootte en renderen het huidige kaartvenster
1map = QgsLayoutItemMap(layout) 2# Set map item position and size (by default, it is a 0 width/0 height item placed at 0,0) 3map.attemptMove(QgsLayoutPoint(5,5, QgsUnitTypes.LayoutMillimeters)) 4map.attemptResize(QgsLayoutSize(200,200, QgsUnitTypes.LayoutMillimeters)) 5# Provide an extent to render 6map.zoomToExtent(iface.mapCanvas().extent()) 7layout.addLayoutItem(map)
label — maakt het weergeven van labels mogelijk. Het is mogelijk het lettertype, de kleur, de uitlijning en marge aan te passen
label = QgsLayoutItemLabel(layout) label.setText("Hello world") label.adjustSizeToText() layout.addLayoutItem(label)
legenda
legend = QgsLayoutItemLegend(layout) legend.setLinkedMap(map) # map is an instance of QgsLayoutItemMap layout.addLayoutItem(legend)
schaalbalk
1item = QgsLayoutItemScaleBar(layout) 2item.setStyle('Numeric') # optionally modify the style 3item.setLinkedMap(map) # map is an instance of QgsLayoutItemMap 4item.applyDefaultSize() 5layout.addLayoutItem(item)
pijl
afbeelding
basisvorm
op knopen gebaseerde vorm
1polygon = QPolygonF() 2polygon.append(QPointF(0.0, 0.0)) 3polygon.append(QPointF(100.0, 0.0)) 4polygon.append(QPointF(200.0, 100.0)) 5polygon.append(QPointF(100.0, 200.0)) 6 7polygonItem = QgsLayoutItemPolygon(polygon, layout) 8layout.addLayoutItem(polygonItem) 9 10props = {} 11props["color"] = "green" 12props["style"] = "solid" 13props["style_border"] = "solid" 14props["color_border"] = "black" 15props["width_border"] = "10.0" 16props["joinstyle"] = "miter" 17 18symbol = QgsFillSymbol.createSimple(props) 19polygonItem.setSymbol(symbol)
tabel
Als een item eenmaal is toegevoegd aan de lay-out kan het worden verplaatst en de grootte worden gewijzigd:
item.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters))
item.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters))
Standaard wordt een kader rondom elk item getekend. U kunt dat als volgt verwijderen:
# for a composer label
label.setFrameEnabled(False)
Naast het handmatig maken van items voor afdruklay-out, heeft QGIS ondersteuning voor sjablonen van afdruklay-out wat in essentie lay-outs zijn met al hun items, opgeslagen als een bestand .qpt (met syntaxis XML).
Als de lay-out eenmaal gereed is (de items van afdruklay-out zijn gemaakt en toegevoegd aan de lay-out), kunnen we doorgaan en een raster- en/of vector-uitvoer produceren.
10.3.1. Lay-out exporteren
De klasse QgsLayoutExporter
moet worden gebruikt om een lay-out te exporteren.
1base_path = os.path.join(QgsProject.instance().homePath())
2pdf_path = os.path.join(base_path, "output.pdf")
3
4exporter = QgsLayoutExporter(layout)
5exporter.exportToPdf(pdf_path, QgsLayoutExporter.PdfExportSettings())
Gebruik exportToImage()
in het geval dat u wilt exporteren naar een afbeelding in plaats van een bestand PDF.
10.3.2. Een afdrukatlas exporteren
Als u alle pagina’s wilt exporteren van een lay-out die de optie Atlas heeft geconfigureerd en ingeschakeld, dient u de methode atlas()
te gebruiken voor het exporteren (QgsLayoutExporter
) met enkele kleine aanpassingen. In het volgende voorbeeld worden de pagina’s geëxporteerd naar afbeeldingen PNG:
exporter.exportToImage(layout.atlas(), base_path, 'png', QgsLayoutExporter.ImageExportSettings())
Onthoud dat de uitvoer zal worden opgeslagen in de map voor het basispad, met de expressie voor de bestandsnaam voor de uitvoer die werd geconfigureerd in Atlas.