Programowo sprawdzać kliknięcie myszy w PyQGIS?

19

Chcę wiedzieć, jak sprawdzić kliknięcie myszy w QGIS. Próbuję napisać wtyczkę python i chcę zapewnić funkcjonalność podobną do narzędzia „Select Single Feature”, które już istnieje w QGIS.

Sprawdziłem dokumenty QGIS API i znalazłem

QgsMapCanvas::CanvasProperties::mouseButtonDown

Brzmi obiecująco. Mam obiekt QgsMapCanvas, ale nie widzę, jak uzyskać dostęp do atrybutu mouseButtonDown.

Jestem zupełnie nowy w QGIS API.

Robert
źródło

Odpowiedzi:

23

Najlepszym sposobem na utworzenie nowego narzędzia, takiego jak Wybierz jedną cechę, jest dziedziczenie z QgsMapToolklasy. Gdy narzędzie jest aktywne, co można ustawić za pomocą QgsMapCanvas::setMapTooldowolnego zdarzenia klawiatury lub kliknięcia, płótno zostanie przekazane do niestandardowego narzędzia.

Oto podstawowa QgsMapToolklasa

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

Możesz robić, co potrzebujesz canvasReleaseEvent, itp

Aby ustawić to narzędzie jako aktywne, wystarczy:

tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)
Nathan W.
źródło
Dziękuję za odpowiedź. To jest dokładnie to, czego potrzebuję. Jednak gdy próbuję wdrożyć to rozwiązanie, pojawia się następujący błąd:class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined . Jakieś pomysły?
Robert
1
Musisz użyć from qgis.gui import QgsMapToolna górze
Nathan W
Ostatnie pytanie ... W jaki sposób dezaktywujesz to narzędzie?
Robert
Ustaw maptool na coś innego lub na None. Zapisałbym to, co wybrał użytkownik, QgsMapCanvas.mapTool()przywracając go po zakończeniu.
Nathan W.
@NathanW „Aby ustawić maptool na coś innego” oznacza również, że klikam „Pan Map” na pasku narzędzi, prawda?
wannik
3

Myślę, że możesz to zrobić za pomocą kombinacji QGIS „canvasClicked”, ale także SIGNAL / SLOTS, aby poradzić sobie z odpowiedzią:

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

Nie wypróbowano, ale powinno dać ci więcej informacji na początek. Jest tu samouczek, w którym ktoś używa tego do zbudowania bardzo podstawowej wtyczki.

Dan
źródło
1
Korzystają z wbudowanej QgsMapToolEmitPointklasy, która da ci podstawowy start do narzędzia. Dobrym sposobem na połączenie się z sygnałami w PyQt jest użycie tej składniself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W
1

Spróbuj czegoś takiego (to jest wybór punktu):

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
źródło
Używałbym tej self.clickTool.canvasClicked.connect(self.handleMouseDown)składni do łączenia się z sygnałami, ponieważ jest ona znacznie czystsza.
Nathan W