Controllare programmaticamente il clic del mouse in PyQGIS?


19

Voglio sapere come verificare la presenza di un clic del mouse in QGIS. Sto cercando di scrivere un plug-in Python e voglio fornire funzionalità simili allo strumento "Seleziona funzionalità singola" che esiste già in QGIS.

Ho controllato i documenti API di QGIS e ho trovato

QgsMapCanvas::CanvasProperties::mouseButtonDown

Sembra promettente. Ho un oggetto QgsMapCanvas ma non riesco a vedere come accedere all'attributo mouseButtonDown.

Sono completamente nuovo all'API QGIS.

Risposte:


23

Il modo migliore per creare un nuovo strumento come lo strumento Seleziona funzionalità singola è ereditare dalla QgsMapToolclasse. Quando il tuo strumento è attivo, che può essere impostato usando QgsMapCanvas::setMapTool, qualsiasi evento di tastiera o clic che la tela ottiene verrà passato al tuo strumento personalizzato.

Ecco una QgsMapToolclasse di base

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

Puoi fare quello di cui hai bisogno canvasReleaseEvent, ecc

Per attivare questo strumento è sufficiente:

tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)

Grazie per la vostra risposta. È esattamente quello di cui ho bisogno. Tuttavia, quando provo attuazione di questa soluzione ottengo il seguente errore: class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined. Qualche idea?
Robert

1
Dovrai utilizzare from qgis.gui import QgsMapToolin alto
Nathan W,

Ultima domanda ... Come si disattiva questo strumento?
Robert

Imposta maptool su qualcos'altro o su None. Vorrei salvare ciò che l'utente ha selezionato usando QgsMapCanvas.mapTool()ripristinandolo dopo aver finito.
Nathan W,

@NathanW "Per impostare maptool su qualcos'altro" significa anche che faccio clic su "Pan Map" sulla barra degli strumenti, giusto?
Wannik,

3

Penso che puoi farlo con una combinazione di QGIS "canvasClicked" ma anche SIGNAL / SLOTS per gestire la risposta:

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

Non provato ma dovresti darti qualche informazione in più per iniziare a guardare. C'è un tutorial qui in cui qualcuno lo sta usando per creare un plugin molto semplice.


1
Stanno usando la QgsMapToolEmitPointclasse integrata che ti darà l'inizio di base per uno strumento. Un buon modo per connettersi ai segnali in PyQt è usare questa sintassiself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W

1

Prova qualcosa del genere (questo è per selezionare 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 )

self.clickTool.canvasClicked.connect(self.handleMouseDown)Userei la sintassi per connettermi ai segnali in quanto è molto più pulito.
Nathan W,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.