Vérifier systématiquement le clic de souris dans PyQGIS?

19

Je veux savoir comment vérifier un clic de souris dans QGIS. J'essaie d'écrire un plugin python et je veux fournir des fonctionnalités similaires à l'outil "Select Single Feature" qui existe déjà dans QGIS.

J'ai vérifié les documents de l'API QGIS et j'ai trouvé

QgsMapCanvas::CanvasProperties::mouseButtonDown

Cela semble prometteur. J'ai un objet QgsMapCanvas mais je ne vois pas comment accéder à l'attribut mouseButtonDown.

Je suis complètement nouveau sur l'API QGIS.

robert
la source

Réponses:

23

La meilleure façon de créer un nouvel outil comme l'outil Sélectionner une entité unique est d'hériter de la QgsMapToolclasse. Lorsque votre outil est actif, ce qui peut être défini à l'aide de QgsMapCanvas::setMapTooltout événement de clavier ou de clic que le canevas obtient sera transmis à votre outil personnalisé.

Voici une QgsMapToolclasse de 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

Vous pouvez faire ce dont vous avez besoin canvasReleaseEvent, etc.

Pour activer cet outil, il vous suffit de:

tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)
Nathan W
la source
Merci pour votre réponse. C'est exactement ce dont j'ai besoin. Cependant, lorsque je tente la mise en œuvre de cette solution que je reçois l'erreur suivante: class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined. Des idées?
robert
1
Vous devrez utiliser from qgis.gui import QgsMapToolen haut
Nathan W
Dernière question ... Comment désactiver alors cet outil?
robert
Définissez maptool sur autre chose ou sur None. Je voudrais enregistrer ce que l'utilisateur a sélectionné en le QgsMapCanvas.mapTool()restaurant après avoir terminé.
Nathan W
@NathanW "Pour définir maptool sur autre chose" signifie également que je clique sur "Pan Map" dans la barre d'outils, non?
wannik
3

Je pense que vous pouvez le faire avec une combinaison de l'utilisation de QGIS "canvasClicked" mais aussi de SIGNAL / SLOTS pour gérer la réponse:

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

Pas essayé mais devrait vous donner plus d'informations pour commencer à regarder. Il y a un tutoriel ici où quelqu'un l'utilise pour construire un plugin très basique.

Dan
la source
1
Ils utilisent la QgsMapToolEmitPointclasse intégrée qui vous donnera le départ de base pour un outil. Une bonne façon de se connecter aux signaux dans PyQt utilise cette syntaxeself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W
1

Essayez quelque chose comme ça (c'est pour sélectionner un point):

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
la source
J'utiliserais la self.clickTool.canvasClicked.connect(self.handleMouseDown)syntaxe pour me connecter aux signaux car c'est beaucoup plus propre.
Nathan W