waigani's diary

QGISを中心にFOSS4Gをいじくる

QGIS APIで印刷その2

QgsCompositionクラスを使ってみる

その1の内容をQgsCompositionクラスを使って書き換えます
あくまでQgsCompositionの使い方の参考程度に

書き換えてみました

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class printPDF():

    #共通で使う設定は__init__の中で
    def __init__(self, canvas, dir):
        self.canvas = canvas
        self.render = canvas.mapRenderer()
        self.dir = dir
        
        #最後に設定を戻すので取っておく
        self.originalDpi = self.render.outputDpi()
        self.originalSize = self.render.outputSize()
        
        #出力デバイスの定義 A4 LandscapeのPDFで出力
        self.printer = QPrinter(QPrinter.ScreenResolution)
        self.printer.setResolution(300)
        self.printer.setOutputFormat(QPrinter.PdfFormat)
        self.printer.setPageSize(QPrinter.A4)
        self.printer.setDocName("printer test")
        self.printer.setOrientation(QPrinter.Landscape)
        
        #出力デバイスから、描画領域を取得
        self.originX = self._dot2mm(self.printer.pageRect().left(), self.printer.resolution())
        self.originY = self._dot2mm(self.printer.pageRect().top(), self.printer.resolution())
        self.drawableWidth = self._dot2mm(self.printer.pageRect().width() - self.printer.pageRect().left(), self.printer.resolution())
        self.drawableHeight = self._dot2mm(self.printer.pageRect().height() - self.printer.pageRect().top(), self.printer.resolution())
        
    #dot→mm変換
    def _dot2mm(self, inDot, dpi):
        outMM = float(inDot) / float(dpi) * 25.4
        return outMM
        
    #指定外接矩形に合わせて描画範囲を変える
    def drawMap(self, bound, id):
        
        #指定図形のidをファイル名としています
        self.printer.setOutputFileName(dir+str(id)+r".pdf")
        
        #指定図形の外接矩形にcanvasをセット
        #refreshはお好みで
        self.canvas.setExtent(bound)
        self.canvas.refresh()
        
        #QgsComposition作成
        #座標の指定がmmなので注意
        composer = QgsComposition(self.render)
        composer.setPlotStyle(QgsComposition.Print)
        composer.setPaperSize(self.printer.widthMM(), self.printer.heightMM())
        composer.setPrintResolution(self.printer.resolution())
        
        #地図配置
        #座標の指定がmmなので注意
        composerMap = QgsComposerMap(composer, self.originX, self.originY, self.drawableWidth, self.drawableHeight)
        composer.addItem(composerMap)
        
        #タイトル配置
        #座標の指定がmmなので注意
        composerLabel = QgsComposerLabel(composer)
        composerLabel.setText(u"印刷テスト")
        composerLabel.setFont(QFont("Arial",24))
        composerLabel.adjustSizeToText()
        composerLabel.setItemPosition(self.originX, self.originY)
        composer.addItem(composerLabel)
        
        #描画
        paint = QPainter(self.printer)
        paperRectMM = self.printer.pageRect(QPrinter.Millimeter)
        paperRectPixel = self.printer.pageRect(QPrinter.DevicePixel)
        composer.render(paint, paperRectPixel, paperRectMM)
        paint.end()
        
        self.render.setOutputSize(self.originalSize, self.originalDpi)

実行する際は

pythonコンソールから実行できます。
あらかじめ前述のクラスを設定の上で、図形を1つずつ渡してあげます。

iface = qgis.utils.iface

#出力先を C:\pdfディレクトリとしておきます
dir = r"C:\pdf\\"

#初期設定をしておく
pMap = printPDF(iface.mapCanvas(), dir)

#各図形の外接長方形を出力範囲としてPDF作成
boxs = 

feat = QgsFeature()
layer = iface.activeLayer()
provider = layer.dataProvider()
provider.select(, provider.extent(), True, True)

#外接矩形とidだけ取っておく
while provider.nextFeature(feat):
    boxs.append([feat.geometry().boundingBox(),feat.id()])

for box,id in boxs:
    pMap.drawMap(box, id)

気になる点など

  • QgsCompositionクラスを使うと、座標の指定がmmで出来るのでレイアウトが楽になります
  • 本当はQgsCompositionを先に作っておき各QgsComposerItemを配置、QgsComposerMap内の描画範囲だけ指定外接矩形に変更したかったのですが、一緒にQgsComposerMapの描画サイズも変えられてしまうのでこのやり方にしています
  • おまけにQgsComposerMapの描画サイズ変更の基準が縦方向だけになっているみたいなので、それもちょっと困る