Secara terprogram memeriksa klik mouse di PyQGIS?

19

Saya ingin tahu cara memeriksa klik mouse di QGIS. Saya mencoba menulis plugin python dan ingin memberikan fungsionalitas yang mirip dengan alat "Select Single Feature" yang sudah ada di QGIS.

Saya memeriksa dokumen api QGIS dan menemukan

QgsMapCanvas::CanvasProperties::mouseButtonDown

Ini kedengarannya menjanjikan. Saya memiliki objek QgsMapCanvas tetapi saya tidak bisa melihat cara mengakses atribut mouseButtonDown.

Saya benar-benar baru di API QGIS.

robert
sumber

Jawaban:

23

Cara terbaik untuk membuat alat baru seperti alat Select Single Feature adalah dengan mewarisi dari QgsMapToolkelas. Saat alat Anda aktif, yang dapat diatur menggunakan QgsMapCanvas::setMapTool, sembarang keyboard atau klik yang didapat kanvas akan diteruskan ke alat kustom Anda.

Ini QgsMapToolkelas dasar

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

Anda dapat melakukan apa yang Anda butuhkan canvasReleaseEvent, dll

Untuk mengaktifkan alat ini, Anda cukup melakukan:

tool = PointTool(qgis.iface.mapCanvas())
qgis.iface.mapCanvas().setMapTool(tool)
Nathan W
sumber
Terima kasih atas tanggapan Anda. Persis seperti yang saya butuhkan. Namun, ketika saya mencoba menerapkan solusi ini saya mendapatkan error berikut: class PointTool(QgsMapTool): NameError: name 'QgsMapTool' is not defined. Ada ide?
robert
1
Anda harus menggunakan from qgis.gui import QgsMapTooldi bagian atas
Nathan W
Pertanyaan terakhir ... Bagaimana Anda menonaktifkan alat ini?
robert
Atur maptool ke sesuatu yang lain, atau ke None. Saya akan menyimpan apa yang telah dipilih pengguna dengan QgsMapCanvas.mapTool()mengembalikannya setelah Anda selesai.
Nathan W
@NathanW "Untuk mengatur maptool ke sesuatu yang lain" juga berarti saya mengklik 'Pan Map' pada toolbar, kan?
wannik
3

Saya pikir Anda dapat melakukan ini dengan kombinasi menggunakan QGIS "canvasClicked" tetapi juga SIGNAL / SLOTS untuk menangani respons:

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

Tidak mencoba tetapi harus memberi Anda beberapa informasi lebih lanjut untuk mulai melihat. Ada tutorial di sini di mana seseorang menggunakan ini untuk membangun plugin yang sangat mendasar.

Dan
sumber
1
Mereka menggunakan QgsMapToolEmitPointkelas bawaan yang akan memberi Anda awal dasar untuk sebuah alat. Cara yang baik untuk terhubung ke sinyal di PyQt adalah menggunakan sintaks iniself.clickTool.canvasClicked.connect(self.handleMouseDown)
Nathan W
1

Coba sesuatu seperti ini (ini untuk memilih titik):

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
sumber
Saya akan menggunakan self.clickTool.canvasClicked.connect(self.handleMouseDown)sintaks untuk terhubung ke sinyal karena jauh lebih bersih.
Nathan W