QGIS 3 Get Coordinates from Mouse Click – How to Retrieve Coordinates Using Python in QGIS

pyqt5pythonqgisqgis-3

I am working on a small QGIS Python plugin and want to get the X/Y coordinates from a user click on the canvas. I have a small UI called from button in a toolbar. After filling the UI with information I would like to get the XY coordinates. I am using QGIS 3 with Python 3 and QT5.

I tried to use the steps from
How to get co ordinates of points on mouse click in PyQGIS
but when running it jumps right to the end without calling the display_point function and there is no reaction to mouse clicks.
Are there any changes to the current QGIS version?

My code, which is inside the plugin class and called by a button from the toolbar without UI.

def run2(self):
    # a reference to our map canvas 
    canvas = iface.mapCanvas() 

    # this QGIS tool emits as QgsPoint after each click on the map canvas
    pointTool = QgsMapToolEmitPoint(canvas)
    # Checkpoint
    print("S 1")
    pointTool.canvasClicked.connect( self.display_point )
    canvas.setMapTool( pointTool )
    # Checkpoint
    print("S 3")

def display_point( pointTool ): 

    print('({:.4f}, {:.4f})'.format(pointTool[0], pointTool[1]))
    # Checkpoint
    print("S 2")

Best Answer

In a plugin (displayed "Always On Top"), with PyQGIS 3, to avoid it jumps right to the end without calling the display_point function you need following changes in your code:

.
.
.
from PyQt5.QtCore import Qt

from qgis.gui import QgsMapToolEmitPoint
.
.
.
    def __init__(self, iface):
        """Constructor.
.
.
.
        # Create the dialog (after translation) and keep reference
        self.dlg = WhereAmIDialog()
        self.dlg.setWindowFlags(Qt.WindowStaysOnTopHint)
.
.
.
    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
.
.
.       
        result = self.pointTool.canvasClicked.connect(self.display_point)
.
.
.
    def display_point(self, point, button):  
        # report map coordinates from a canvas click
        coords = "{}, {}".format(point.x(), point.y())
        self.dlg.lineEdit.setText(str(coords)) 
        self.dlg.show()
.
.
.
    def run(self):
        """Run method that performs all the real work"""
        # make our clickTool the tool that we'll use for now    
        self.canvas.setMapTool(self.pointTool)
.
.
.

It works; as it can be observed at following image:

enter image description here