I want to know how to check for a mouse click in QGIS. I am trying to write a Python plugin and want to provide functionality similar to the "Select Single Feature" tool that already exists in QGIS.
I checked the QGIS API docs and found
QgsMapCanvas::CanvasProperties::mouseButtonDown
This sounds promising. I have a QgsMapCanvas
object but I can't see how to access the mouseButtonDown
attribute.
3 Answers 3
The best way to make a new tool like the Select Single Feature tool is to inherit from the QgsMapTool
class. When your tool is active, which can be set using QgsMapCanvas::setMapTool
, any keyboard or click events the canvas gets will be passed onto your custom tool.
Here is a basic QgsMapTool
class
class PointTool(QgsMapTool):
def __init__(self, canvas):
QgsMapTool.__init__(self, canvas)
self.canvas = canvas
def canvasPressEvent(self, event):
pass
def canvasMoveEvent(self, event):
x = event.pos().x()
y = event.pos().y()
point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
def canvasReleaseEvent(self, event):
#Get the click
x = event.pos().x()
y = event.pos().y()
point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
def activate(self):
pass
def deactivate(self):
pass
def isZoomTool(self):
return False
def isTransient(self):
return False
def isEditTool(self):
return True
You can do what you need in canvasReleaseEvent
, etc
To set this tool active you just do:
tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)
-
Thank you for your response. Its exactly what I need. However, when I try implementing this solution I get the following error:
class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined
. Any ideas?robert– robert2013年01月03日 12:34:32 +00:00Commented Jan 3, 2013 at 12:34 -
1You will need to use
from qgis.gui import QgsMapTool
at the topNathan W– Nathan W2013年01月03日 12:39:29 +00:00Commented Jan 3, 2013 at 12:39 -
Last question... How do you then deactivate this tool?robert– robert2013年01月03日 12:49:38 +00:00Commented Jan 3, 2013 at 12:49
-
Set maptool to something else, or to
None
. I would save what the user had selected usingQgsMapCanvas.mapTool()
restoring it after you are done.Nathan W– Nathan W2013年01月03日 13:01:53 +00:00Commented Jan 3, 2013 at 13:01 -
@NathanW "To set maptool to something else" also means that I click 'Pan Map' on the toolbar, right?wannik– wannik2014年11月22日 12:51:56 +00:00Commented Nov 22, 2014 at 12:51
I think you can do this with a combination of using QGIS "canvasClicked" but also SIGNAL/SLOTS to deal with the response:
result = QObject.connect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.handleMouseDown)
Not tried but should give you some more information to start looking at. There is a tutorial here where someone is using this to build a very basic plugin.
-
1They are using the built in
QgsMapToolEmitPoint
class which will give you the basic start for a tool. A good way to connect to signals in PyQt is using this syntaxself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W– Nathan W2013年01月03日 12:35:47 +00:00Commented Jan 3, 2013 at 12:35
Try something like this (this is to select a point):
def run(self):
self.pointEmitter = QgsMapToolEmitPoint(self.iface.mapCanvas())
QObject.connect( self.pointEmitter, SIGNAL("canvasClicked(const QgsPoint, Qt::MouseButton)"), self.selectNow)
self.iface.mapCanvas().setMapTool( self.pointEmitter )
def selectNow(self, point, button):
#QMessageBox.information(None, "Clicked coords", " x: " + str(point.x()) + " Y: " + str(point.y()) )
layer = self.iface.activeLayer()
if not layer or layer.type() != QgsMapLayer.VectorLayer:
QMessageBox.warning(None, "No!", "Select a vector layer")
return
width = self.iface.mapCanvas().mapUnitsPerPixel() * 2
rect = QgsRectangle(point.x() - width,
point.y() - width,
point.x() + width,
point.y() + width)
rect = self.iface.mapCanvas().mapRenderer().mapToLayerCoordinates(layer, rect)
layer.select([], rect)
feat = QgsFeature()
ids = []
while layer.nextFeature(feat):
ids.append( feat.id() )
layer.setSelectedFeatures( ids )
-
I would use the
self.clickTool.canvasClicked.connect(self.handleMouseDown)
syntax to connect to signals as it's much cleaner.Nathan W– Nathan W2013年01月04日 04:41:35 +00:00Commented Jan 4, 2013 at 4:41