¿Verifica progresivamente el clic del mouse en PyQGIS?

19

Quiero saber cómo verificar un clic del mouse en QGIS. Estoy tratando de escribir un complemento de Python y quiero proporcionar una funcionalidad similar a la herramienta "Seleccionar característica única" que ya existe en QGIS.

Revisé los documentos de la API de QGIS y encontré

QgsMapCanvas::CanvasProperties::mouseButtonDown

Esto suena prometedor. Tengo un objeto QgsMapCanvas pero no puedo ver cómo acceder al atributo mouseButtonDown.

Soy completamente nuevo en la API QGIS.

robert
fuente

Respuestas:

23

La mejor manera de crear una nueva herramienta como la herramienta Seleccionar característica única es heredar de la QgsMapToolclase. Cuando su herramienta está activa, que se puede configurar usando QgsMapCanvas::setMapTool, cualquier teclado o evento de clic que obtenga el lienzo se pasará a su herramienta personalizada.

Aquí hay una QgsMapToolclase básica

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

Puedes hacer lo que necesites canvasReleaseEvent, etc.

Para configurar esta herramienta activa, simplemente haga lo siguiente:

tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)
Nathan W
fuente
Gracias por su respuesta. Es exactamente lo que necesito. Sin embargo, cuando intento implementar esta solución me sale el siguiente error: class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined. ¿Algunas ideas?
robert
1
Tendrá que usar from qgis.gui import QgsMapToolen la parte superior
Nathan W
Última pregunta ... ¿Cómo se desactiva esta herramienta?
robert
Establezca maptool en otra cosa, o en None. Guardaría lo que el usuario había seleccionado al QgsMapCanvas.mapTool()restaurarlo después de que haya terminado.
Nathan W
@NathanW "Para configurar maptool a otra cosa" también significa que hago clic en 'Pan Map' en la barra de herramientas, ¿verdad?
wannik
3

Creo que puede hacer esto con una combinación de usar QGIS "canvasClicked" pero también SEÑAL / RANURAS para lidiar con la respuesta:

result = QObject.connect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.handleMouseDown)

No lo he intentado, pero debería darle más información para comenzar a mirar. Aquí hay un tutorial en el que alguien está usando esto para crear un complemento muy básico.

Dan
fuente
1
Están utilizando la QgsMapToolEmitPointclase integrada que le dará el comienzo básico para una herramienta. Una buena forma de conectarse a las señales en PyQt es usar esta sintaxisself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W
1

Pruebe algo como esto (esto es para seleccionar un punto):

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 )
André Barriguinha
fuente
self.clickTool.canvasClicked.connect(self.handleMouseDown)Usaría la sintaxis para conectarme a las señales, ya que es mucho más limpia.
Nathan W