Below code can be use to get the X,Y Coordinate of clicked location .
class PrintSnappedPoint(QgsMapToolEmitPoint):
def __init__(self, canvas):
self.canvas = canvas
QgsMapToolEmitPoint.__init__(self, self.canvas)
self.l = iface.activeLayer()
self.i = QgsSnapIndicator(self.canvas)
self.u = self.canvas.snappingUtils()
self.c = self.u.config()
self.c.setEnabled(True)
self.c.setMode(QgsSnappingConfig.AdvancedConfiguration)
self.s = QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 25.00,
QgsTolerance.Pixels)
self.c.setIndividualLayerSettings(self.l, self.s)
self.u.setConfig(self.c)
def canvasMoveEvent(self, e):
m = self.u.snapToMap(e.pos())
self.i.setMatch(m)
def canvasPressEvent(self, e):
print("not called")
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:3111"),
QgsCoordinateReferenceSystem("EPSG:4326"), QgsProject.instance())
if self.i.match().type():
pointxy = self.i.match().point()
else:
pointxy = None
if pointxy:
point = [pointxy.x(), pointxy.y()]
print('Point snapped to vertex: {}'.format(point))
def deactivate(self):
self.s = QgsSnappingConfig.IndividualLayerSettings(False, QgsSnappingConfig.Vertex , 25.00,
QgsTolerance.Pixels)
self.c.setIndividualLayerSettings(self.l, self.s)
self.u.setConfig(self.c)
canvas = iface.mapCanvas()
T = PrintSnappedPoint(canvas)
canvas.setMapTool(T)
I wanted to implement same code with bottom click in QGIS plugin and want to get X, Y location and add them into two line edits X Coordinate and Y Coordinate.
I added below code to run method but the canvasMoveEvent
function is not being called and does not affect any thing in map canvas.
def run(self):
"""Run method that performs all the real work"""
# Create the dialog with elements (after translation) and keep reference
# Only create GUI ONCE in callback, so that it will only load when the plugin is started
if self.first_start == True:
self.first_start = False
self.dlg = ChidoByougaDialog()
#conneting to function
self.dlg.pushButton_2.clicked.connect(self.get_wakaban_coords)
# show the dialog
self.dlg.show()
self.dlg.exec_()
def get_wakaban_coords(self):
canvas = self.iface.mapCanvas()
T = PrintSnappedPoint(canvas,self.iface)
canvas.setMapTool(T)
class PrintSnappedPoint(QgsMapToolEmitPoint):
def __init__(self, canvas,iface):
self.iface = iface
self.canvas = canvas
QgsMapToolEmitPoint.__init__(self, self.canvas)
print("come upto here")
self.l = self.iface.activeLayer()
self.i = QgsSnapIndicator(self.canvas)
self.u = self.canvas.snappingUtils()
self.c = self.u.config()
self.c.setEnabled(True)
self.c.setMode(QgsSnappingConfig.AdvancedConfiguration)
self.s = QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 25.00,
QgsTolerance.Pixels)
self.c.setIndividualLayerSettings(self.l, self.s)
self.u.setConfig(self.c)
print("lower end")
def canvasMoveEvent(self, e):
print("come to mouse event")
m = self.u.snapToMap(e.pos())
self.i.setMatch(m)
print("not here")
def canvasPressEvent(self, e):
print("not called")
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:3111"),
QgsCoordinateReferenceSystem("EPSG:4326"), QgsProject.instance())
if self.i.match().type():
pointxy = self.i.match().point()
else:
pointxy = None
if pointxy:
point = [pointxy.x(), pointxy.y()]
print('Point snapped to vertex: {}'.format(point))
def deactivate(self):
self.s = QgsSnappingConfig.IndividualLayerSettings(False, QgsSnappingConfig.Vertex, 25.00,
QgsTolerance.Pixels)
self.c.setIndividualLayerSettings(self.l, self.s)
self.u.setConfig(self.c)
Is there any proper way to get location clicked by user and store in the Line Edit?
1 Answer 1
Below is a complete, minimal, working plugin script which shows how to do what you what. I saved this file as __init__.py
, placed it in a folder with an appropriate metadata.txt file and copied the folder into the QGIS plugins directory.
Note that to populate the line edit in the plugin dialog with the coordinates from mouse clicks on the map canvas, we need to add a parent
argument to the map tool class constructor. Then when we instantiate the map tool class we pass in the plugin dialog (self.dlg
) as the parent object. This allows us to access the dialog widgets from within the map tool class and use methods such as setText()
when overriding the canvasPressEvent()
method.
#-----------------------------------------------------------
# Copyright (C) 2021 Ben Wirf
#-----------------------------------------------------------
# Licensed under the terms of GNU GPL 2
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#---------------------------------------------------------------------
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QAction, QDialog, QLabel, QLineEdit, QPushButton,
QGridLayout)
from qgis.core import QgsProject, QgsTolerance, QgsSnappingConfig, QgsCoordinateTransform
from qgis.gui import QgsMapToolEmitPoint, QgsSnapIndicator
def classFactory(iface):
return GetSnappedMapPoint(iface)
class GetSnappedMapPoint:
def __init__(self, iface):
self.iface = iface
self.dlg = MyDialog(self.iface)
self.T = None
def initGui(self):
self.action = QAction('Launch', self.iface.mainWindow())
self.action.triggered.connect(self.run)
self.iface.addToolBarIcon(self.action)
self.dlg.btn.clicked.connect(self.get_wakaban_coords)
def unload(self):
self.iface.removeToolBarIcon(self.action)
del self.action
def run(self):
self.dlg.show()
def get_wakaban_coords(self):
self.T = PrintSnappedPoint(self.iface, self.dlg)
self.iface.mapCanvas().setMapTool(self.T)
class MyDialog(QDialog):
def __init__(self, iface):
self.iface = iface
QDialog.__init__(self)
self.setGeometry(200, 200, 600, 200)
self.lbl = QLabel('Point snapped to vertex:', self)
self.line_edit = QLineEdit(self)
self.btn = QPushButton('Set map tool', self)
self.layout = QGridLayout()
self.layout.addWidget(self.lbl, 0, 0, 1, 1, Qt.AlignCenter)
self.layout.addWidget(self.line_edit, 0, 1, 1, 2)
self.layout.addWidget(self.btn, 1, 1, 1, 1)
self.setLayout(self.layout)
self.setWindowFlags(Qt.WindowStaysOnTopHint)
def closeEvent(self, e):
self.line_edit.clear()
self.iface.actionPan().trigger()
class PrintSnappedPoint(QgsMapToolEmitPoint):
def __init__(self, iface, parent):
#Note constructor takes a parent argument, a reference to
#which is stored as self.parent
self.iface = iface
self.parent = parent
self.canvas = self.iface.mapCanvas()
QgsMapToolEmitPoint.__init__(self, self.canvas)
self.l = self.iface.activeLayer()
self.i = QgsSnapIndicator(self.canvas)
self.u = self.canvas.snappingUtils()
self.c = self.u.config()
self.c.setEnabled(True)
self.c.setMode(QgsSnappingConfig.AdvancedConfiguration)
self.s = QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 25.00,
QgsTolerance.Pixels)
self.c.setIndividualLayerSettings(self.l, self.s)
self.u.setConfig(self.c)
def canvasMoveEvent(self, e):
m = self.u.snapToMap(e.pos())
self.i.setMatch(m)
def canvasPressEvent(self, e):
if self.i.match().type():
pointxy = self.i.match().point()
else:
pointxy = None
if pointxy:
if self.l.crs() != QgsProject.instance().crs():
x_form = QgsCoordinateTransform(QgsProject.instance().crs(),
self.l.crs(),
QgsProject.instance())
tr = x_form.transform(pointxy)
point = [tr.x(), tr.y()]
else:
point = [pointxy.x(), pointxy.y()]
#Here we can access widgets in the plugin dialog
#using the self.parent reference
self.parent.line_edit.clear()
self.parent.line_edit.setText('{}'.format(point))
def deactivate(self):
self.s = QgsSnappingConfig.IndividualLayerSettings(False, QgsSnappingConfig.Vertex, 25.00,
QgsTolerance.Pixels)
self.c.setIndividualLayerSettings(self.l, self.s)
self.u.setConfig(self.c)
You can see how it works in the short screencast below:
You can find a minimal QGIS plugin template in this very useful resource from Martin Dobias here:
-
@Devenepali, you're welcome :-)Ben W– Ben W2021年09月23日 06:57:49 +00:00Commented Sep 23, 2021 at 6:57
Explore related questions
See similar questions with these tags.
__init__()
method of your plugin class e.g.self.iface = iface
andself.canvas = self.iface.mapCanvas()
. 2. Also create the instance of the map tool class in the__init__()
method e.g.self.T = printSnappedPoint(self.canvas, self.iface)
. Then in the methodget_wakaban_points()
just do:self.canvas.setMapTool(self.T)
. I will try to post an answer later.parent
argument to the map tool class constructor, create a class attribute (self.parent = parent
) and pass your plugin dialog (self.dlg
) as the parent. You can then access the dialog widgets from inside the map tool class e.g.self.parent.line_edit.setText(str(point))
to replace the print statement.