4

I am trying to write a python plugin and want to provide functionality similar to the "Identify feature" tool that already exists in QGIS. Plus the possibility to open the document relied to a feature by getting the path assigned to it in a column. How does one get, after launching the plugin, the clicked feature on mouse click event?

I've used some code from here but I couldn't get it to work.

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *

class IdentifyGeometry(QgsMapToolIdentify):
 def __init__(self, canvas):
  self.canvas = canvas
  QgsMapToolIdentify.__init__(self, canvas)

 def canvasReleaseEvent(self, mouseEvent):
  results = self.identify(mouseEvent.x(),mouseEvent.y(), self.TopDownStopAtFirst, self.VectorLayer)
  if len(results) > 0:
   self.emit( SIGNAL( "geomIdentified" ), results[0].mLayer, results[0].mFeature)

2 Answers 2

6

This can be done by using QgsMapToolEmitPoint class. With each mouse click is generated a QgsPoint whose coordinates are used for corroborating if this point is in or out some vector feature. If answer is "yes", its id is used to get infomation stored in attributes table. You can adapt following code, where attribute retrieved is named 'name', for your plugin.

from qgis.gui import QgsMapToolEmitPoint

def display_point(point, mouse_button): 

    coords = "Map Coordinates: {:.4f}, {:.4f}".format(point.x(), point.y())

    print coords

    layer = iface.activeLayer()
    feats = [ feat for feat in layer.getFeatures() ]

    geo_pt = QgsGeometry.fromPoint(QgsPoint(point.x(), point.y()))

    id = -1

    for feat in feats:
        if geo_pt.within(feat.geometry()):
            id = feat.id()
            break

    if id != -1:
        print feats[id].attribute('name')
    else:
        print "no feature selected"

# a reference to our map canvas 
canvas = iface.mapCanvas() 

# this QGIS tool emits as QgsPoint after each click on the map canvas
pointTool = QgsMapToolEmitPoint(canvas)

pointTool.canvasClicked.connect(display_point)

canvas.setMapTool(pointTool)

I tried it out with vector file of following image:

enter image description here

After running above code, each mouse click at Map Canvas of QGIS is printed as point coordinates at Python Console and, if it corresponds, its attribute named 'name'. Above image reveals that clicks were realized outside whatever vector feature for first two points and, for the remaning points, inside of some vector feature. Vector attributes table was used for corroborating that field 'name' values were obtained as expected.

3
  • I needed to make some changes and now it's working, Thank you ! Aug 16, 2018 at 14:02
  • You're welcome and good for you that it's finally working in your plugin!
    – xunilk
    Aug 16, 2018 at 14:13
  • there is a constraint, this code must iterate on all records of the layer which take too much time :/ Aug 16, 2018 at 14:59
4

here is a solution that works for me:
when I launch the plugin the select tool is selected automatically
self.iface.actionSelect().trigger()

then I get the active layer

    selectedLayer=self.iface.activeLayer()
    if selectedLayer:
        selectedLayer.selectionChanged.connect(self.featureSelected)
    self.iface.legendInterface().currentLayerChanged.connect(self.layerChanged)

then I get the selected features

selection = selectedLayer.selectedFeatures()
if len(selection)>0:
    print selection[0].attribute('Layer')

this is the full code

def featureSelected(self):    
    global selectedLayer
    QApplication.instance().setOverrideCursor(Qt.ArrowCursor)
    selection = selectedLayer.selectedFeatures()
    if len(selection)>0:
        print selection[0].attribute('Layer')
def layerChanged(self):
    global selectedLayer
    selectedLayer=self.iface.activeLayer()
    if selectedLayer:
        selectedLayer.selectionChanged.connect(self.canvasReleaseEvent)
def run(self):
    global selectedLayer
    self.iface.actionSelect().trigger()
    self.iface.mapCanvas().setSelectionColor( QColor("magenta"))

    self.dlg.buttonBox.accepted.connect(self.open_files)
    self.dlg.buttonBox.rejected.connect(self.close)

    selectedLayer=self.iface.activeLayer()
    if selectedLayer:
        selectedLayer.selectionChanged.connect(self.canvasReleaseEvent)
    self.iface.legendInterface().currentLayerChanged.connect(self.layerChanged)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.