マップキャンバスウィジェットは、おそらくQGIS内で最も重要なウィジェットです。なぜなら、オーバーレイされた地図レイヤーで構成された地図を表示し、地図とレイヤーの間のやりとりを可能にするからです。キャンバスは、常に現在のキャンバスの範囲で定義された地図の一部を表示します。やりとりは**地図ツール**を使用して行われます:パン、ズーム、レイヤーの識別、計測、ベクトル編集などのツールがあります。他のグラフィックスプログラムと同様に、常に1つのツールがアクティブになっていて、使用可能なツールは切り替えできます。
マップキャンバスは:class:QgsMapCanvas クラスの:mod:` qgis.gui` モジュールで実装されています。実装はQt Graphics Viewフレームワークに基づいています。このフレームワークは、一般に、カスタムグラフィックアイテムが配置され、ユーザがそれらと相互作用できる表面およびビューを提供します。ここではユーザがグラフィックシーン、ビュー、アイテムのコンセプトを理解するのに十分に精通していることを仮定しています。そうでない場合は、フレームワークの概要<http://qt-project.org/doc/qt-4.8/graphicsview.html> `_ を必ず読んでください。
地図がパン、ズームイン/アウト(または他の操作によって更新が発生)するたびに、地図は現在の範囲内で再び投影されます。レイヤーは画像に投影され(:class: `QgsMapRenderer`クラスを使用して)、その画像がキャンバスに表示されます。マップを表示するグラフィックアイテム(Qtグラフィックスビューフレームワークに関して)は、:class: `QgsMapCanvasMap`クラスです。このクラスは、投影された地図の更新も制御します。バックグラウンドとして機能するこのアイテムの他にも**マップキャンバスアイテム**はありえます。典型的なマップキャンバスアイテムは、ラバーバンド(計測、ベクトル編集などに使用)や頂点マーカーです。キャンバスアイテムは、通常、新しいポリゴンを作成するときなど、マップツールの視覚的フィードバックを表示するために使用されます。マップツールは、ポリゴンの現在の形状を示すラバーバンドキャンバスアイテムを作成します。すべてのマップキャンバスアイテムは:class: `QgsMapCanvasItem`のサブクラスで、基本的な``QGraphicsItem``オブジェクトにいくつかの機能を追加します。
要約すると、マップキャンバスアーキテクチャは3つのコンセプトからなります:
マップキャンバス — 地図の可視化
マップキャンバスアイテム—マップキャンバスで表示できる追加アイテム
マップツールズ—マップキャンバスのインタラクション
マップキャンバスは他のQtウィジェットと同じようにウィジェットなので、使い方は簡単です
canvas = QgsMapCanvas()
canvas.show()
これは、マップキャンバスを備えたスタンドアロンのウィンドウを生成します。既存のウィジェットまたはウィンドウに埋め込むこともできます。 .uiファイルとQt Designerを使用する場合は、フォーム上に `` QWidget``を置いてクラス名として `` QgsMapCanvas``を設定し、ヘッダファイルとして `` qgis.gui``を設定して新しいクラスにします。 `` pyuic4``ユーティリティーがそれを処理します。これは、キャンバスを埋め込む非常に便利な方法です。もう1つの可能性は、マップキャンバスや他のウィジェット(メインウィンドウやダイアログの子として)を構築し、レイアウトを作成するためのコードを手作業で書くことです。
デフォルトでは、マップキャンバスの背景色は黒でありアンチエイリアスは使用されません。背景を白に設定し、投影をなめらかにするためのアンチエイリアスを有効にするには
canvas.setCanvasColor(Qt.white)
canvas.enableAntiAliasing(True)
(不思議に思われる場合は ``Qt``は PyQt4.QtCore``モジュールから来ていると Qt.white``は、事前に定義された``QColor``インスタンスの一つである。、)
今度は地図レイヤーをいくつか追加します。最初にレイヤーを開き、地図レイヤーレジストリに追加します。次に、キャンバスの範囲を設定し、キャンバスのレイヤーのリストを設定します
layer = QgsVectorLayer(path, name, provider)
if not layer.isValid():
raise IOError, "Failed to open the layer"
# add layer to the registry
QgsMapLayerRegistry.instance().addMapLayer(layer)
# set extent to the extent of our layer
canvas.setExtent(layer.extent())
# set the map canvas layer set
canvas.setLayerSet([QgsMapCanvasLayer(layer)])
これらのコマンドを実行した後、キャンバスには読み込んだレイヤーが表示されているはずです。
次の例では、マップキャンバスと地図のパンとズームのための基本的なマップツールを含むウィンドウを作成します。各ツールを起動するためのアクションが作成されます。パンは:class: QgsMapToolPan で行います。クラスは:class:` QgsMapToolZoom` のインスタンスでズームイン/ズームアウトします。アクションはチェック可能に設定され、アクションのチェック/非チェック状態を自動的に処理(マップツールがアクティブになると、そのアクションに選択済みのマークが付き、以前のマップツールのアクションが選択解除される)できるように後ほどツールに割り当てられます。マップツールは:func: setMapTool メソッドを使って起動されます。
from qgis.gui import *
from PyQt4.QtGui import QAction, QMainWindow
from PyQt4.QtCore import SIGNAL, Qt, QString
class MyWnd(QMainWindow):
def __init__(self, layer):
QMainWindow.__init__(self)
self.canvas = QgsMapCanvas()
self.canvas.setCanvasColor(Qt.white)
self.canvas.setExtent(layer.extent())
self.canvas.setLayerSet([QgsMapCanvasLayer(layer)])
self.setCentralWidget(self.canvas)
actionZoomIn = QAction(QString("Zoom in"), self)
actionZoomOut = QAction(QString("Zoom out"), self)
actionPan = QAction(QString("Pan"), self)
actionZoomIn.setCheckable(True)
actionZoomOut.setCheckable(True)
actionPan.setCheckable(True)
self.connect(actionZoomIn, SIGNAL("triggered()"), self.zoomIn)
self.connect(actionZoomOut, SIGNAL("triggered()"), self.zoomOut)
self.connect(actionPan, SIGNAL("triggered()"), self.pan)
self.toolbar = self.addToolBar("Canvas actions")
self.toolbar.addAction(actionZoomIn)
self.toolbar.addAction(actionZoomOut)
self.toolbar.addAction(actionPan)
# create the map tools
self.toolPan = QgsMapToolPan(self.canvas)
self.toolPan.setAction(actionPan)
self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in
self.toolZoomIn.setAction(actionZoomIn)
self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out
self.toolZoomOut.setAction(actionZoomOut)
self.pan()
def zoomIn(self):
self.canvas.setMapTool(self.toolZoomIn)
def zoomOut(self):
self.canvas.setMapTool(self.toolZoomOut)
def pan(self):
self.canvas.setMapTool(self.toolPan)
上記のコードはファイル、例えば:file: `mywnd.py`に入れ、QGIS内のPythonコンソールで試すことができます。このコードは、現在選択されているレイヤーを新しく作成されたキャンバスに配置します
import mywnd
w = mywnd.MyWnd(qgis.utils.iface.activeLayer())
w.show()
Just make sure that the mywnd.py file is located within Python search path (sys.path). If it isn’t, you can simply add it: sys.path.insert(0, '/my/path') — otherwise the import statement will fail, not finding the module.
キャンバス内の地図にさらにデータを表示するには、マップキャンバスアイテムを使用します。カスタムのキャンバスアイテムクラスを作成することができます(以下で説明します)。便利な2つの便利なキャンバスアイテムクラスがあります。ポリラインやポリゴンを描画するための:class: QgsRubberBand 、描画ポイントのための:class:` QgsVertexMarker` です。それらは両方ともマップ座標で動作するため、キャンバスがパンまたはズームされるときにはシェイプは自動的に移動/拡大縮小されます。
ポリラインを表示するには
r = QgsRubberBand(canvas, False) # False = not a polygon
points = [QgsPoint(-1, -1), QgsPoint(0, 1), QgsPoint(1, -1)]
r.setToGeometry(QgsGeometry.fromPolyline(points), None)
ポリゴンを表示するには
r = QgsRubberBand(canvas, True) # True = a polygon
points = [[QgsPoint(-1, -1), QgsPoint(0, 1), QgsPoint(1, -1)]]
r.setToGeometry(QgsGeometry.fromPolygon(points), None)
ポリゴンの点が普通のリストではないことに注意してください。実際には、多角形の線状の環を含有する環のリストです:最初のリングは外側の境界であり、さらに(オプションの)環はポリゴンの穴に対応します。
ラバーバンドはいくらかカスタマイズできます、すなわち、その色と線幅を変更することがが可能です
r.setColor(QColor(0, 0, 255))
r.setWidth(3)
キャンバスアイテムはキャンバスシーンにバインドされています。それらを一時的に隠す(そして再表示する)には、hide`と:func:() show`のコンボを使います。アイテムを完全に削除するには、キャンバスのシーンから削除する必要があります
canvas.scene().removeItem(r)
(C ++ではアイテムを削除することだけ可能ですが、Pythonでは `` del r``は参照を削除するだけでありオブジェクトはキャンバスの所有物なのでそのまま残ります)
ラバーバンドはポイントを描画するためにも使用できますが、これには:class: QgsVertexMarker`クラスの方が適しています(:class: QgsRubberBand`だと目的のポイントの周りに矩形を描くだけになるでしょう)。頂点マーカーの使い方は
m = QgsVertexMarker(canvas)
m.setCenter(QgsPoint(0, 0))
これは[0,0]の位置に赤い十字を描きます。アイコンの種類、サイズ、色、ペンの幅はカスタマイズできます
m.setColor(QColor(0, 255, 0))
m.setIconSize(5)
m.setIconType(QgsVertexMarker.ICON_BOX) # or ICON_CROSS, ICON_X
m.setPenWidth(3)
一時的な頂点マーカーの隠蔽とキャンバスからそれらを除去するために、ラバーバンドと同じことが適用されます。
自分でカスタムツールを書くことで、キャンバス上でユーザーが実行するアクションにカスタム動作を実装できます。
地図ツールは:class:QgsMapTool`クラスまたは派生クラスから継承し、既に見たように:func: setMapTool`メソッドを使用してキャンバス内のアクティブなツールとして選択する必要があります。
キャンバスをクリックしてドラッグすることで矩形範囲を定義できるマップツールの例を次に示します。矩形が定義されると、境界座標がコンソールに表示されます。前述のラバーバンド要素を使用して、選択されている矩形が定義されていることを示します。
class RectangleMapTool(QgsMapToolEmitPoint):
def __init__(self, canvas):
self.canvas = canvas
QgsMapToolEmitPoint.__init__(self, self.canvas)
self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
self.rubberBand.setColor(Qt.red)
self.rubberBand.setWidth(1)
self.reset()
def reset(self):
self.startPoint = self.endPoint = None
self.isEmittingPoint = False
self.rubberBand.reset(QGis.Polygon)
def canvasPressEvent(self, e):
self.startPoint = self.toMapCoordinates(e.pos())
self.endPoint = self.startPoint
self.isEmittingPoint = True
self.showRect(self.startPoint, self.endPoint)
def canvasReleaseEvent(self, e):
self.isEmittingPoint = False
r = self.rectangle()
if r is not None:
print "Rectangle:", r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum()
def canvasMoveEvent(self, e):
if not self.isEmittingPoint:
return
self.endPoint = self.toMapCoordinates(e.pos())
self.showRect(self.startPoint, self.endPoint)
def showRect(self, startPoint, endPoint):
self.rubberBand.reset(QGis.Polygon)
if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y():
return
point1 = QgsPoint(startPoint.x(), startPoint.y())
point2 = QgsPoint(startPoint.x(), endPoint.y())
point3 = QgsPoint(endPoint.x(), endPoint.y())
point4 = QgsPoint(endPoint.x(), startPoint.y())
self.rubberBand.addPoint(point1, False)
self.rubberBand.addPoint(point2, False)
self.rubberBand.addPoint(point3, False)
self.rubberBand.addPoint(point4, True) # true to update canvas
self.rubberBand.show()
def rectangle(self):
if self.startPoint is None or self.endPoint is None:
return None
elif self.startPoint.x() == self.endPoint.x() or self.startPoint.y() == self.endPoint.y():
return None
return QgsRectangle(self.startPoint, self.endPoint)
def deactivate(self):
super(RectangleMapTool, self).deactivate()
self.emit(SIGNAL("deactivated()"))
マップキャンバスアイテムを作成する方法
import sys
from qgis.core import QgsApplication
from qgis.gui import QgsMapCanvas
def init():
a = QgsApplication(sys.argv, True)
QgsApplication.setPrefixPath('/home/martin/qgis/inst', True)
QgsApplication.initQgis()
return a
def show_canvas(app):
canvas = QgsMapCanvas()
canvas.show()
app.exec_()
app = init()
show_canvas(app)