Отрисовка карты и печать

Существует два способа получить печатную карту из исходных данных: простой и быстрый используя QgsMapRenderer или создание и тщательная настройка компоновки используя QgsComposition и сопутствующие классы.

Простая отрисовка

Render some layers using QgsMapRenderer — create destination paint device (QImage, QPainter etc.), set up layer set, extent, output size and do the rendering

# create image
img = QImage(QSize(800, 600), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(255, 255, 255)
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# set layer set
lst = [layer.getLayerID()]  # add ID of every layer
render.setLayerSet(lst)

# set extent
rect = QgsRect(render.fullExtent())
rect.scale(1.1)
render.setExtent(rect)

# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)

p.end()

# save image
img.save("render.png","png")

Rendering layers with different CRS

If you have more than one layer and they have a different CRS, the simple example above will probably not work: to get the right values from the extent calculations you have to explicitly set the destination CRS and enable OTF reprojection as in the example below (only the renderer configuration part is reported)

...
# set layer set
layers = QgsMapLayerRegistry.instance().mapLayers()
lst = layers.keys()
render.setLayerSet(lst)

# Set destination CRS to match the CRS of the first layer
render.setDestinationCrs(layers.values()[0].crs())
# Enable OTF reprojection
render.setProjectionsEnabled(True)
...

Вывод с использованием компоновщика карт

Компоновщик карт это удобный инструмент для создания более сложных печатных карт, по сравнению с простой отрисовкой описанной выше. Используя компоновщик можно создавать составные компоновки, содержащие карты, подписи, легенду, таблицы и другие элементы, которые обычно присутсвуют на печатных картах. Готовую компоновку можно экспортировать в PDF, растровое изображение или сразу же распечатать на принтере.

The composer consists of a bunch of classes. They all belong to the core library. QGIS application has a convenient GUI for placement of the elements, though it is not available in the GUI library. If you are not familiar with Qt Graphics View framework, then you are encouraged to check the documentation now, because the composer is based on it.

The central class of the composer is QgsComposition which is derived from QGraphicsScene. Let us create one

mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)

Обратите вниманием, что компоновка принимает в качестве параметра экземпляр QgsMapRenderer. Предполагается, что код выполняется в среде QGIS и поэтому используется рендер активной карты. Компоновка использует различные параметры рендера, и самое главное — набор слоёв карты и текущий охват. При использовании компоновщика в самостоятельном приложении необходимо создать свой собственный экземпляр рендера, как это показано в разделе выше, и передать его в компоновку.

К компоновке можно добавлять разные элементы (карту, подписи, ...) — все они являются потомками класса QgsComposerItem. В настоящее время доступны следующие элементы:

  • map — this item tells the libraries where to put the map itself. Here we create a map and stretch it over the whole paper size

    x, y = 0, 0
    w, h = c.paperWidth(), c.paperHeight()
    composerMap = QgsComposerMap(c, x ,y, w, h)
    c.addItem(composerMap)
    
  • label — allows displaying labels. It is possible to modify its font, color, alignment and margin

    composerLabel = QgsComposerLabel(c)
    composerLabel.setText("Hello world")
    composerLabel.adjustSizeToText()
    c.addItem(composerLabel)
    
  • legend

    legend = QgsComposerLegend(c)
    legend.model().setLayerSet(mapRenderer.layerSet())
    c.addItem(legend)
    
  • scale bar

    item = QgsComposerScaleBar(c)
    item.setStyle('Numeric') # optionally modify the style
    item.setComposerMap(composerMap)
    item.applyDefaultSize()
    c.addItem(item)
    
  • стрелка севера

  • изображение

  • фигура

  • таблица

By default the newly created composer items have zero position (top left corner of the page) and zero size. The position and size are always measured in millimeters

# set label 1cm from the top and 2cm from the left of the page
composerLabel.setItemPosition(20, 10)
# set both label's position and size (width 10cm, height 3cm)
composerLabel.setItemPosition(20, 10, 100, 30)

A frame is drawn around each item by default. How to remove the frame

composerLabel.setFrame(False)

Помимо создания элементов компоновки вручную QGIS поддерживает шаблоны компоновок, которые являются компоновками со всеми элементами, сохраненными в файл .qpt (формат XML). К сожалению, этот функционал пока ещё не доступен в API.

После того как компоновка готова (все элементы созданы и добавлены к компоновке), можно приступать к представлению результатов в растровой или векторной форме.

The default output settings for composition are page size A4 and resolution 300 DPI. You can change them if necessary. The paper size is specified in millimeters

c.setPaperSize(width, height)
c.setPrintResolution(dpi)

Вывод в растровое изображение

The following code fragment shows how to render a composition to a raster image

dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())

# create output image and initialize it
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(0)

# render the composition
imagePainter = QPainter(image)
sourceArea = QRectF(0, 0, c.paperWidth(), c.paperHeight())
targetArea = QRectF(0, 0, width, height)
c.render(imagePainter, targetArea, sourceArea)
imagePainter.end()

image.save("out.png", "png")

Вывод в формате PDF

The following code fragment renders a composition to a PDF file

printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("out.pdf")
printer.setPaperSize(QSizeF(c.paperWidth(), c.paperHeight()), QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(c.printResolution())

pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
c.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()