Programmatisch auf Mausklick in PyQGIS prüfen?

19

Ich möchte wissen, wie man in QGIS nach einem Mausklick sucht. Ich versuche, ein Python-Plugin zu schreiben, und möchte Funktionen bereitstellen, die dem in QGIS bereits vorhandenen Tool "Select Single Feature" ähneln.

Ich überprüfte die QGIS-API-Dokumente und fand sie

QgsMapCanvas::CanvasProperties::mouseButtonDown

Das klingt vielversprechend. Ich habe ein QgsMapCanvas-Objekt, kann aber nicht sehen, wie ich auf das mouseButtonDown-Attribut zugreifen kann.

Ich bin völlig neu in der QGIS-API.

Robert
quelle

Antworten:

23

Die beste Möglichkeit, ein neues Werkzeug wie das Werkzeug "Einzelfeature auswählen" zu erstellen, besteht darin, von der QgsMapToolKlasse zu erben . Wenn Ihr Werkzeug aktiv ist und mit festgelegt werden kann QgsMapCanvas::setMapTool, werden alle Tastatur- oder Klickereignisse, die die Zeichenfläche erhält, an Ihr benutzerdefiniertes Werkzeug übergeben.

Hier ist eine einfache QgsMapToolKlasse

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

Sie können tun, was Sie brauchen canvasReleaseEvent, usw

Um dieses Tool zu aktivieren, gehen Sie wie folgt vor:

tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)
Nathan W
quelle
Danke für Ihre Antwort. Es ist genau das, was ich brauche. Allerdings, wenn ich diese Lösung versuchen Umsetzung bekomme ich folgende Fehlermeldung: class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined. Irgendwelche Ideen?
Robert
1
Sie müssen from qgis.gui import QgsMapToolan der Spitze verwenden
Nathan W
Letzte Frage ... Wie können Sie dieses Tool dann deaktivieren?
Robert
Stellen Sie maptool auf etwas anderes oder auf None. Ich würde speichern, was der Benutzer ausgewählt hat, QgsMapCanvas.mapTool()indem ich es wieder herstelle, nachdem Sie fertig sind.
Nathan W
@ NathanW "MapTool auf etwas anderes einstellen" bedeutet auch, dass ich in der Symbolleiste auf "Map verschieben" klicke, oder?
Wannik
3

Ich denke, Sie können dies mit einer Kombination aus der Verwendung von QGIS "canvasClicked", aber auch SIGNAL / SLOTS tun, um mit der Antwort fertig zu werden:

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

Nicht ausprobiert, sollte Ihnen aber weitere Informationen geben, die Sie sich ansehen sollten. Hier gibt es ein Tutorial, in dem jemand damit ein sehr einfaches Plugin erstellt.

Dan
quelle
1
Sie verwenden die eingebaute QgsMapToolEmitPointKlasse, die Ihnen den grundlegenden Start für ein Werkzeug gibt. Eine gute Möglichkeit, eine Verbindung zu Signalen in PyQt herzustellen, ist die Verwendung dieser Syntaxself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W
1

Versuchen Sie so etwas (um einen Punkt auszuwählen):

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
quelle
Ich würde die self.clickTool.canvasClicked.connect(self.handleMouseDown)Syntax verwenden, um eine Verbindung zu Signalen herzustellen, da sie viel sauberer ist.
Nathan W