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.

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)

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.


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 )

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.