In this recipe, we'll create a tool to draw polygons on the canvas. This tool is an important tool because it opens the doors to even more advanced tools. Once you have a polygon on the canvas, you can do all sorts of operations that involve querying and geometry.
We will use the application framework from the Adding standard map tools to the canvas recipe, so complete that recipe. We will extend that application with a new tool. The complete version of this application is available in the code samples provided with this book.
We will add a new tool to the toolbar and also create a class that describes our polygon tool, as follows:
QAction("Pan")
method:actionPoly = QAction("Polygon", self)
actionPoly.setCheckable(True)
self.connect(actionPoly, SIGNAL("triggered()"), self.poly)
self.toolbar.addAction(actionPoly)
self.toolPoly = PolyMapTool(self.canvas) self.toolPoly.setAction(actionPoly)
self.poly()
def poly(self): self.canvas.setMapTool(self.toolPoly)
Now, we create a class that describes the type of tool we have and the output it provides. The output is a point on the canvas defined in the canvasPressEvent
method, which receives the button-click event and the showPoly
method. We will inherit from a generic tool in order to create points called the QgsMapToolEmitPoint
; we will also use an object called QgsRubberBand
for handling polygons:
classPolyMapTool(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.point = None self.points = [] defcanvasPressEvent(self, e): self.point = self.toMapCoordinates(e.pos()) m = QgsVertexMarker(self.canvas) m.setCenter(self.point) m.setColor(QColor(0,255,0)) m.setIconSize(5) m.setIconType(QgsVertexMarker.ICON_BOX) m.setPenWidth(3) self.points.append(self.point) self.isEmittingPoint = True self.showPoly() defshowPoly(self): self.rubberband.reset(QGis.Polygon) for point in self.points[:-1]: self.rubberband.addPoint(point, False) self.rubberband.addPoint(self.points[-1], True) self.rubberband.show()
All the settings for the polygon are contained in the custom class. There is a key property, called EmittingPoint, which we use to detect whether we are still adding points to the polygon. This value starts out as false
. If this is the case, we reset our polygon object and begin drawing a new one. The following screenshot shows a polygon drawn with this tool on a map: