Building a custom selection tool

In this recipe, we will build a custom tool that both draws a shape on the map and interacts with other features on the map. These two basic functions are the basis for almost any map tool you would want to build, either in a standalone QGIS application like this one, or by extending the QGIS desktop application with a plugin.

Getting ready

We will use the application framework from the Adding standard map tools to the canvas recipe, so complete that recipe first. 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. It will also be beneficial to study the other two tool-related recipes, A map tool to draw polygons or lines on the canvas and A map tool to draw points on the canvas, as this recipe builds on them as well.

You will also need the following zipped shapefile from https://geospatialpython.googlecode.com/files/NYC_MUSEUMS_GEO.zip.

Download and extract it to your qgis_data directory.

How to do it...

We will add a new tool to the toolbar and also create a class describing our selection tool, including how to draw the selection polygon and how to select the features. To do this, we need to perform the following steps:

  1. First, we define our polygon tool's button in the actions portion of our application. Place this line after the QAction("Pan") method:
    actionSelect = QAction("Select", self)
    
  2. In the next section, we make sure that when we click on the button, it stays selected:
    actionSelect.setCheckable(True)
    
  3. In the section after that, we define the method used when the button is triggered:
    self.connect(actionSelect, SIGNAL("triggered()"), self.select)
    
  4. Now, we add the button to the toolbar along with the other buttons:
    self.toolbar.addAction(actionSelect)
    
  5. Then, we link the application to our specialized tool class:
    self.toolSelect = SelectMapTool(self.canvas, self.lyr)
    self.toolSelect.setAction(actionSelect)
    
  6. We set the point tool to be selected when the application loads:
    self.select()
    
  7. Now, we define the method in the main application class for our tool:
    def select(self):
    self.canvas.setMapTool(self.toolSelect)
    
  8. Next, we create a class that describes the type of tool we have and how it works. The output is a point on the canvas defined in the canvasPressEvent method, which receives the button click-event and the selectPoly method. We will inherit from a generic tool to create points called the QgsMapToolEmitPoint; we will also use an object called QgsRubberBand to handle polygons. However, we must also perform the selection process to highlight the features that fall within our selection polygon:
    classSelectMapTool(QgsMapToolEmitPoint):
    def __init__(self, canvas, lyr):
    self.canvas = canvas
    self.lyr = lyr
    QgsMapToolEmitPoint.__init__(self, self.canvas)
    self.rubberband = QgsRubberBand(self.canvas, QGis.Polygon)
    self.rubberband.setColor(QColor(255,255,0,50))
    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.selectPoly()
    
    defselectPoly(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() 
    iflen(self.points) > 2:
    g = self.rubberband.asGeometry()
    featsPnt = self.lyr.getFeatures(QgsFeatureRequest().setFilterRect(g.boundingBox()))
    forfeatPnt in featsPnt:
    iffeatPnt.geometry().within(g):
    self.lyr.select(featPnt.id()) 
    

How it works...

QGIS has a generic tool for highlighting features, but in this case, we can use the standard selection functionality, which simplifies our code. With the exception of a dialog to load new layers and the ability to show attributes, we have a very basic but nearly complete standalone GIS application.The following screenshot shows the selection tool in action:

How it works...
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset