以编程方式检查PyQGIS中的鼠标单击?


19

我想知道如何在QGIS中检查鼠标单击。我正在尝试编写python插件,并希望提供类似于QGIS中已经存在的“选择单个功能”工具的功能。

我检查了QGIS api文档并发现

QgsMapCanvas::CanvasProperties::mouseButtonDown

这听起来很有希望。我有一个QgsMapCanvas对象,但看不到如何访问mouseButtonDown属性。

我对QGIS API完全陌生。

Answers:


23

制作新工具(例如“选择单个要素”工具)的最佳方法是从QgsMapTool类继承。当您的工具处于活动状态(可以使用设置)时QgsMapCanvas::setMapTool,画布获取的任何键盘或单击事件都会传递到您的自定义工具上。

这是基础QgsMapTool

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

您可以在中执行所需的操作canvasReleaseEvent,等等

要将此工具设置为活动状态,只需执行以下操作:

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

谢谢您的答复。这正是我所需要的。但是,当我尝试实现此解决方案时,出现以下错误:class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined。有任何想法吗?
罗伯特

1
您需要from qgis.gui import QgsMapTool在顶部使用
Nathan W

最后一个问题...然后如何停用此工具?
罗伯特

将maptool设置为其他值或None。完成后,我将使用QgsMapCanvas.mapTool()恢复它来保存用户选择的内容。
内森·W

@NathanW“将maptool设置为其他内容”还意味着我单击工具栏上的“ Pan Map”,对吗?
wannik 2014年

3

我认为您可以结合使用QGIS“ canvasClicked”和SIGNAL / SLOTS来处理响应:

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

没有尝试过,但是应该给您一些更多的信息以开始研究。这里有一个教程,其中有人使用它来构建一个非常基本的插件。


1
他们正在使用内置的QgsMapToolEmitPoint类,它将为您提供工具的基本入门。在PyQt中连接信号的一种好方法是使用这种语法self.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W

1

尝试这样的事情(这是选择一个点):

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)语法来连接信号,因为它更清洁。
内森·W
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.