[{"data":1,"prerenderedAt":1864},["ShallowReactive",2],{"doc:\u002Fqgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002Fcapture-map-click-coordinates-pyqgis":3},{"id":4,"title":5,"body":6,"description":1853,"extension":1854,"meta":1855,"navigation":277,"path":1860,"seo":1861,"stem":1862,"__hash__":1863},"docs\u002Fqgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002Fcapture-map-click-coordinates-pyqgis\u002Findex.md","Capture Map Click Coordinates in PyQGIS",{"type":7,"value":8,"toc":1840},"minimark",[9,13,35,44,204,209,235,239,245,393,426,430,433,679,694,698,701,880,896,900,903,1096,1269,1281,1285,1288,1378,1381,1510,1532,1536,1542,1604,1614,1618,1687,1691,1703,1707,1728,1737,1752,1761,1771,1780,1789,1795,1809,1813,1836],[10,11,5],"h1",{"id":12},"capture-map-click-coordinates-in-pyqgis",[14,15,16,17,21,22,26,27,30,31,34],"p",{},"Reading where the user clicked is the smallest useful interaction a plugin can offer, and it comes with a coordinate-system trap at every step. The mouse event carries ",[18,19,20],"em",{},"widget pixels",". ",[23,24,25],"code",{},"toMapCoordinates()"," gives you the ",[18,28,29],{},"canvas CRS",". The layer you want to compare against may be in a ",[18,32,33],{},"third"," CRS. Skipping any conversion produces numbers that look plausible and are wrong — which is much harder to notice than an exception.",[14,36,37,38,43],{},"This page is a focused recipe within ",[39,40,42],"a",{"href":41},"\u002Fqgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002F","Custom Map Tools and Canvas Interaction",". It covers the ready-made emit-point tool, the conversion chain, reporting a position in a different CRS such as WGS84, and tracking coordinates live as the cursor moves.",[14,45,46],{},[47,48,53,57,61,68,85,94,104,109,114,119,125,128,131,133,136,139,143,148,151,155,159,164,168,171,174,177,184,188,192,199],"svg",{"viewBox":49,"role":50,"ariaLabel":51,"xmlns":52},"0 0 760 258","img","The conversion chain from widget pixels through canvas map coordinates to layer coordinates and finally to a display CRS such as WGS84","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[54,55,56],"title",{},"Four coordinate spaces, three conversions",[58,59,60],"desc",{},"A click begins as widget pixels with the origin at the canvas top-left. toMapCoordinates converts it to the canvas CRS. toLayerCoordinates converts it further into the layer's own CRS, which is what a geometry comparison needs. A separate coordinate transform converts it to WGS84 for display to a user.",[62,63],"rect",{"x":64,"y":64,"width":65,"height":66,"fill":67},"0","760","258","#f6f3ea",[69,70,71],"defs",{},[72,73,80],"marker",{"id":74,"viewBox":75,"refX":76,"refY":77,"markerWidth":78,"markerHeight":78,"orient":79},"clickChainArrow","0 0 10 10","8","5","7","auto-start-reverse",[81,82],"path",{"d":83,"fill":84},"M0 0 L10 5 L0 10 z","#0f766e",[86,87,93],"text",{"x":88,"y":89,"style":90,"fill":91,"textAnchor":92},"380","26","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Which space are your numbers in?",[62,95],{"x":96,"y":97,"width":98,"height":99,"rx":100,"fill":101,"stroke":102,"style":103},"12","70","164","94","10","#fffdf7","#2563eb","stroke-width:2.5",[86,105,108],{"x":99,"y":106,"style":107,"fill":102,"textAnchor":92},"96","text-anchor:middle;font-size:11.5px;font-weight:bold;font-family:sans-serif","event.pos()",[86,110,20],{"x":99,"y":111,"style":112,"fill":113,"textAnchor":92},"118","text-anchor:middle;font-size:11px;font-family:sans-serif","#2f3b35",[86,115,118],{"x":99,"y":116,"style":117,"fill":113,"textAnchor":92},"136","text-anchor:middle;font-size:11px;font-family:monospace","(240, 90)",[86,120,124],{"x":99,"y":121,"style":122,"fill":123,"textAnchor":92},"154","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#59645f","y increases downward",[62,126],{"x":127,"y":97,"width":98,"height":99,"rx":100,"fill":101,"stroke":84,"style":103},"204",[86,129,29],{"x":130,"y":106,"style":107,"fill":84,"textAnchor":92},"286",[86,132,25],{"x":130,"y":111,"style":112,"fill":113,"textAnchor":92},[86,134,135],{"x":130,"y":116,"style":117,"fill":113,"textAnchor":92},"504812, 5606340",[86,137,138],{"x":130,"y":121,"style":122,"fill":123,"textAnchor":92},"the project's CRS",[62,140],{"x":141,"y":97,"width":98,"height":99,"rx":100,"fill":142,"stroke":84,"style":103},"396","#26322d",[86,144,147],{"x":145,"y":106,"style":107,"fill":146,"textAnchor":92},"478","#d9f99d","layer CRS",[86,149,150],{"x":145,"y":111,"style":112,"fill":146,"textAnchor":92},"toLayerCoordinates()",[86,152,154],{"x":145,"y":153,"style":122,"fill":146,"textAnchor":92},"140","what a geometry",[86,156,158],{"x":145,"y":157,"style":122,"fill":146,"textAnchor":92},"156","comparison needs",[62,160],{"x":161,"y":97,"width":162,"height":99,"rx":100,"fill":101,"stroke":163,"style":103},"588","160","#b45309",[86,165,167],{"x":166,"y":106,"style":107,"fill":163,"textAnchor":92},"668","display CRS",[86,169,170],{"x":166,"y":111,"style":112,"fill":113,"textAnchor":92},"QgsCoordinateTransform",[86,172,173],{"x":166,"y":153,"style":117,"fill":113,"textAnchor":92},"12.4924, 50.5871",[86,175,176],{"x":166,"y":157,"style":122,"fill":123,"textAnchor":92},"for humans",[178,179],"line",{"x1":180,"y1":181,"x2":182,"y2":181,"stroke":84,"style":183},"176","117","200","stroke-width:2.5;marker-end:url(#clickChainArrow)",[178,185],{"x1":186,"y1":181,"x2":187,"y2":181,"stroke":84,"style":183},"368","392",[178,189],{"x1":190,"y1":181,"x2":191,"y2":181,"stroke":163,"style":183},"560","584",[62,193],{"x":127,"y":194,"width":195,"height":196,"rx":76,"fill":101,"stroke":197,"style":198},"196","356","44","#b91c1c","stroke-width:2",[86,200,203],{"x":201,"y":202,"style":112,"fill":113,"textAnchor":92},"382","223","comparing canvas coordinates to layer geometry: silently wrong",[205,206,208],"h2",{"id":207},"prerequisites","Prerequisites",[210,211,212,220,227],"ul",{},[213,214,215,219],"li",{},[216,217,218],"strong",{},"QGIS 3.34 LTR"," (bundled Python 3.12) or newer, running as a desktop application.",[213,221,222,223,226],{},"A plugin or a Python Console session with ",[23,224,225],{},"iface"," available.",[213,228,229,230,234],{},"Some awareness of the project versus layer CRS distinction — see ",[39,231,233],{"href":232},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002F","Coordinate Reference Systems in PyQGIS",".",[205,236,238],{"id":237},"use-the-ready-made-tool","Use the ready-made tool",[14,240,241,244],{},[23,242,243],{},"QgsMapToolEmitPoint"," exists precisely for this, and using it means writing no event handlers at all.",[246,247,252],"pre",{"className":248,"code":249,"language":250,"meta":251,"style":251},"language-python shiki shiki-themes github-dark","from qgis.gui import QgsMapToolEmitPoint\n\ncanvas = iface.mapCanvas()\ntool = QgsMapToolEmitPoint(canvas)\n\n\ndef report(point, button):\n    print(f\"{point.x():.2f}, {point.y():.2f}\")\n\n\ntool.canvasClicked.connect(report)\ncanvas.setMapTool(tool)\n","python","",[23,253,254,272,279,291,302,307,312,325,371,376,381,387],{"__ignoreMap":251},[255,256,258,262,266,269],"span",{"class":178,"line":257},1,[255,259,261],{"class":260},"snl16","from",[255,263,265],{"class":264},"s95oV"," qgis.gui ",[255,267,268],{"class":260},"import",[255,270,271],{"class":264}," QgsMapToolEmitPoint\n",[255,273,275],{"class":178,"line":274},2,[255,276,278],{"emptyLinePlaceholder":277},true,"\n",[255,280,282,285,288],{"class":178,"line":281},3,[255,283,284],{"class":264},"canvas ",[255,286,287],{"class":260},"=",[255,289,290],{"class":264}," iface.mapCanvas()\n",[255,292,294,297,299],{"class":178,"line":293},4,[255,295,296],{"class":264},"tool ",[255,298,287],{"class":260},[255,300,301],{"class":264}," QgsMapToolEmitPoint(canvas)\n",[255,303,305],{"class":178,"line":304},5,[255,306,278],{"emptyLinePlaceholder":277},[255,308,310],{"class":178,"line":309},6,[255,311,278],{"emptyLinePlaceholder":277},[255,313,315,318,322],{"class":178,"line":314},7,[255,316,317],{"class":260},"def",[255,319,321],{"class":320},"svObZ"," report",[255,323,324],{"class":264},"(point, button):\n",[255,326,328,332,335,338,342,345,348,351,354,357,359,362,364,366,368],{"class":178,"line":327},8,[255,329,331],{"class":330},"sDLfK","    print",[255,333,334],{"class":264},"(",[255,336,337],{"class":260},"f",[255,339,341],{"class":340},"sU2Wk","\"",[255,343,344],{"class":330},"{",[255,346,347],{"class":264},"point.x()",[255,349,350],{"class":260},":.2f",[255,352,353],{"class":330},"}",[255,355,356],{"class":340},", ",[255,358,344],{"class":330},[255,360,361],{"class":264},"point.y()",[255,363,350],{"class":260},[255,365,353],{"class":330},[255,367,341],{"class":340},[255,369,370],{"class":264},")\n",[255,372,374],{"class":178,"line":373},9,[255,375,278],{"emptyLinePlaceholder":277},[255,377,379],{"class":178,"line":378},10,[255,380,278],{"emptyLinePlaceholder":277},[255,382,384],{"class":178,"line":383},11,[255,385,386],{"class":264},"tool.canvasClicked.connect(report)\n",[255,388,390],{"class":178,"line":389},12,[255,391,392],{"class":264},"canvas.setMapTool(tool)\n",[14,394,395,398,399,402,403,406,407,409,410,413,414,417,418,421,422,234],{},[216,396,397],{},"Breakdown:"," ",[23,400,401],{},"canvasClicked"," passes a ",[23,404,405],{},"QgsPointXY"," already converted to the ",[216,408,29],{},", plus the mouse button that was pressed — filter on ",[23,411,412],{},"button == Qt.LeftButton"," if the right button should do something else. In the Python Console the module-level ",[23,415,416],{},"tool"," name keeps the object alive; inside a plugin it must be stored on ",[23,419,420],{},"self",", or QGIS crashes as described in ",[39,423,425],{"href":424},"\u002Fqgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002Fcreate-custom-map-tool-pyqgis\u002F","Create a Custom Map Tool in PyQGIS",[205,427,429],{"id":428},"convert-to-layer-coordinates","Convert to layer coordinates",[14,431,432],{},"The canvas CRS and the layer CRS are frequently different, and comparing across them is the single most common source of a click that never matches anything.",[246,434,436],{"className":248,"code":435,"language":250,"meta":251,"style":251},"from qgis.core import QgsProject\nfrom qgis.gui import QgsMapTool\nfrom qgis.PyQt.QtCore import Qt\n\n\nclass LayerPickTool(QgsMapTool):\n    def __init__(self, canvas, layer):\n        super().__init__(canvas)\n        self.canvas = canvas\n        self.layer = layer\n\n    def canvasReleaseEvent(self, event):\n        if event.button() != Qt.LeftButton:\n            return\n        canvas_point = self.toMapCoordinates(event.pos())\n        layer_point = self.toLayerCoordinates(self.layer, event.pos())\n        print(\"canvas:\", round(canvas_point.x(), 2), round(canvas_point.y(), 2))\n        print(\"layer :\", round(layer_point.x(), 2), round(layer_point.y(), 2))\n",[23,437,438,450,461,473,477,481,497,508,522,535,547,551,561,576,582,596,614,649],{"__ignoreMap":251},[255,439,440,442,445,447],{"class":178,"line":257},[255,441,261],{"class":260},[255,443,444],{"class":264}," qgis.core ",[255,446,268],{"class":260},[255,448,449],{"class":264}," QgsProject\n",[255,451,452,454,456,458],{"class":178,"line":274},[255,453,261],{"class":260},[255,455,265],{"class":264},[255,457,268],{"class":260},[255,459,460],{"class":264}," QgsMapTool\n",[255,462,463,465,468,470],{"class":178,"line":281},[255,464,261],{"class":260},[255,466,467],{"class":264}," qgis.PyQt.QtCore ",[255,469,268],{"class":260},[255,471,472],{"class":264}," Qt\n",[255,474,475],{"class":178,"line":293},[255,476,278],{"emptyLinePlaceholder":277},[255,478,479],{"class":178,"line":304},[255,480,278],{"emptyLinePlaceholder":277},[255,482,483,486,489,491,494],{"class":178,"line":309},[255,484,485],{"class":260},"class",[255,487,488],{"class":320}," LayerPickTool",[255,490,334],{"class":264},[255,492,493],{"class":320},"QgsMapTool",[255,495,496],{"class":264},"):\n",[255,498,499,502,505],{"class":178,"line":314},[255,500,501],{"class":260},"    def",[255,503,504],{"class":330}," __init__",[255,506,507],{"class":264},"(self, canvas, layer):\n",[255,509,510,513,516,519],{"class":178,"line":327},[255,511,512],{"class":330},"        super",[255,514,515],{"class":264},"().",[255,517,518],{"class":330},"__init__",[255,520,521],{"class":264},"(canvas)\n",[255,523,524,527,530,532],{"class":178,"line":373},[255,525,526],{"class":330},"        self",[255,528,529],{"class":264},".canvas ",[255,531,287],{"class":260},[255,533,534],{"class":264}," canvas\n",[255,536,537,539,542,544],{"class":178,"line":378},[255,538,526],{"class":330},[255,540,541],{"class":264},".layer ",[255,543,287],{"class":260},[255,545,546],{"class":264}," layer\n",[255,548,549],{"class":178,"line":383},[255,550,278],{"emptyLinePlaceholder":277},[255,552,553,555,558],{"class":178,"line":389},[255,554,501],{"class":260},[255,556,557],{"class":320}," canvasReleaseEvent",[255,559,560],{"class":264},"(self, event):\n",[255,562,564,567,570,573],{"class":178,"line":563},13,[255,565,566],{"class":260},"        if",[255,568,569],{"class":264}," event.button() ",[255,571,572],{"class":260},"!=",[255,574,575],{"class":264}," Qt.LeftButton:\n",[255,577,579],{"class":178,"line":578},14,[255,580,581],{"class":260},"            return\n",[255,583,585,588,590,593],{"class":178,"line":584},15,[255,586,587],{"class":264},"        canvas_point ",[255,589,287],{"class":260},[255,591,592],{"class":330}," self",[255,594,595],{"class":264},".toMapCoordinates(event.pos())\n",[255,597,599,602,604,606,609,611],{"class":178,"line":598},16,[255,600,601],{"class":264},"        layer_point ",[255,603,287],{"class":260},[255,605,592],{"class":330},[255,607,608],{"class":264},".toLayerCoordinates(",[255,610,420],{"class":330},[255,612,613],{"class":264},".layer, event.pos())\n",[255,615,617,620,622,625,627,630,633,636,639,641,644,646],{"class":178,"line":616},17,[255,618,619],{"class":330},"        print",[255,621,334],{"class":264},[255,623,624],{"class":340},"\"canvas:\"",[255,626,356],{"class":264},[255,628,629],{"class":330},"round",[255,631,632],{"class":264},"(canvas_point.x(), ",[255,634,635],{"class":330},"2",[255,637,638],{"class":264},"), ",[255,640,629],{"class":330},[255,642,643],{"class":264},"(canvas_point.y(), ",[255,645,635],{"class":330},[255,647,648],{"class":264},"))\n",[255,650,652,654,656,659,661,663,666,668,670,672,675,677],{"class":178,"line":651},18,[255,653,619],{"class":330},[255,655,334],{"class":264},[255,657,658],{"class":340},"\"layer :\"",[255,660,356],{"class":264},[255,662,629],{"class":330},[255,664,665],{"class":264},"(layer_point.x(), ",[255,667,635],{"class":330},[255,669,638],{"class":264},[255,671,629],{"class":330},[255,673,674],{"class":264},"(layer_point.y(), ",[255,676,635],{"class":330},[255,678,648],{"class":264},[14,680,681,398,683,686,687,690,691,693],{},[216,682,397],{},[23,684,685],{},"toLayerCoordinates(layer, pos)"," does the pixel conversion ",[18,688,689],{},"and"," the CRS transform into the layer's own system in one call — it is the method to reach for whenever the result will be compared against a geometry. ",[23,692,25],{}," stops at the canvas CRS, which is right for display and wrong for comparison. When the project and layer share a CRS the two return identical values, which is exactly why the bug survives testing on a tidy project and appears on a real one.",[205,695,697],{"id":696},"report-a-position-in-wgs84","Report a position in WGS84",[14,699,700],{},"Users generally want latitude and longitude regardless of what the project uses, so a display transform is worth building once.",[246,702,704],{"className":248,"code":703,"language":250,"meta":251,"style":251},"from qgis.core import (\n    QgsCoordinateReferenceSystem,\n    QgsCoordinateTransform,\n    QgsProject,\n)\n\nproject = QgsProject.instance()\nwgs84 = QgsCoordinateReferenceSystem(\"EPSG:4326\")\nto_wgs84 = QgsCoordinateTransform(project.crs(), wgs84, project)\n\n\ndef report(point, button):\n    geo = to_wgs84.transform(point)\n    iface.statusBarIface().showMessage(\n        f\"{geo.y():.6f}, {geo.x():.6f}  ({project.crs().authid()}: \"\n        f\"{point.x():.1f}, {point.y():.1f})\"\n    )\n",[23,705,706,717,722,727,732,736,740,750,765,775,779,783,791,801,806,847,875],{"__ignoreMap":251},[255,707,708,710,712,714],{"class":178,"line":257},[255,709,261],{"class":260},[255,711,444],{"class":264},[255,713,268],{"class":260},[255,715,716],{"class":264}," (\n",[255,718,719],{"class":178,"line":274},[255,720,721],{"class":264},"    QgsCoordinateReferenceSystem,\n",[255,723,724],{"class":178,"line":281},[255,725,726],{"class":264},"    QgsCoordinateTransform,\n",[255,728,729],{"class":178,"line":293},[255,730,731],{"class":264},"    QgsProject,\n",[255,733,734],{"class":178,"line":304},[255,735,370],{"class":264},[255,737,738],{"class":178,"line":309},[255,739,278],{"emptyLinePlaceholder":277},[255,741,742,745,747],{"class":178,"line":314},[255,743,744],{"class":264},"project ",[255,746,287],{"class":260},[255,748,749],{"class":264}," QgsProject.instance()\n",[255,751,752,755,757,760,763],{"class":178,"line":327},[255,753,754],{"class":264},"wgs84 ",[255,756,287],{"class":260},[255,758,759],{"class":264}," QgsCoordinateReferenceSystem(",[255,761,762],{"class":340},"\"EPSG:4326\"",[255,764,370],{"class":264},[255,766,767,770,772],{"class":178,"line":373},[255,768,769],{"class":264},"to_wgs84 ",[255,771,287],{"class":260},[255,773,774],{"class":264}," QgsCoordinateTransform(project.crs(), wgs84, project)\n",[255,776,777],{"class":178,"line":378},[255,778,278],{"emptyLinePlaceholder":277},[255,780,781],{"class":178,"line":383},[255,782,278],{"emptyLinePlaceholder":277},[255,784,785,787,789],{"class":178,"line":389},[255,786,317],{"class":260},[255,788,321],{"class":320},[255,790,324],{"class":264},[255,792,793,796,798],{"class":178,"line":563},[255,794,795],{"class":264},"    geo ",[255,797,287],{"class":260},[255,799,800],{"class":264}," to_wgs84.transform(point)\n",[255,802,803],{"class":178,"line":578},[255,804,805],{"class":264},"    iface.statusBarIface().showMessage(\n",[255,807,808,811,813,815,818,821,823,825,827,830,832,834,837,839,842,844],{"class":178,"line":584},[255,809,810],{"class":260},"        f",[255,812,341],{"class":340},[255,814,344],{"class":330},[255,816,817],{"class":264},"geo.y()",[255,819,820],{"class":260},":.6f",[255,822,353],{"class":330},[255,824,356],{"class":340},[255,826,344],{"class":330},[255,828,829],{"class":264},"geo.x()",[255,831,820],{"class":260},[255,833,353],{"class":330},[255,835,836],{"class":340},"  (",[255,838,344],{"class":330},[255,840,841],{"class":264},"project.crs().authid()",[255,843,353],{"class":330},[255,845,846],{"class":340},": \"\n",[255,848,849,851,853,855,857,860,862,864,866,868,870,872],{"class":178,"line":598},[255,850,810],{"class":260},[255,852,341],{"class":340},[255,854,344],{"class":330},[255,856,347],{"class":264},[255,858,859],{"class":260},":.1f",[255,861,353],{"class":330},[255,863,356],{"class":340},[255,865,344],{"class":330},[255,867,361],{"class":264},[255,869,859],{"class":260},[255,871,353],{"class":330},[255,873,874],{"class":340},")\"\n",[255,876,877],{"class":178,"line":616},[255,878,879],{"class":264},"    )\n",[14,881,882,884,885,888,889,892,893,895],{},[216,883,397],{}," Constructing the transform once outside the handler avoids rebuilding it on every click, which matters if it is wired to mouse ",[18,886,887],{},"movement"," rather than clicks. Passing ",[23,890,891],{},"project"," as the third argument supplies the transform context so the datum path matches what the GUI would use. Note the output order: latitude then longitude for the geographic pair, which is the convention users expect, while ",[23,894,405],{}," stores x (longitude) first — printing them in storage order is a classic way to send someone to the wrong hemisphere.",[205,897,899],{"id":898},"track-the-cursor-live","Track the cursor live",[14,901,902],{},"A live readout in the status bar is a small feature that makes a plugin feel finished. It runs on every mouse move, so the handler has to stay cheap.",[14,904,905],{},[47,906,909,912,915,918,921,927,1065,1070,1074,1077,1082,1086,1089,1093],{"viewBox":907,"role":50,"ariaLabel":908,"xmlns":52},"0 0 760 244","A comparison of doing work on every mouse move versus only on click, showing that move handlers fire hundreds of times per second and must stay trivial",[54,910,911],{},"Move handlers fire far more often than click handlers",[58,913,914],{},"A timeline over one second of cursor movement shows roughly sixty move events and a single click event. The move handler is annotated as needing to stay trivial — a coordinate conversion and a status bar update — while the click handler can afford a spatial query, a database read or a dialog.",[62,916],{"x":64,"y":64,"width":65,"height":917,"fill":67},"244",[86,919,920],{"x":88,"y":89,"style":90,"fill":91,"textAnchor":92},"One second of interaction — sixty moves, one click",[86,922,926],{"x":180,"y":923,"style":924,"fill":102,"textAnchor":925},"82","text-anchor:end;font-size:12px;font-weight:bold;font-family:sans-serif","end","canvasMoveEvent",[928,929,930,936,938,941,944,947,950,953,956,959,962,965,968,971,974,977,980,983,985,988,991,994,997,1000,1003,1006,1009,1012,1015,1018,1021,1024,1027,1030,1032,1035,1038,1041,1044,1047,1050,1053,1056,1059,1062],"g",{"fill":102},[62,931],{"x":932,"y":933,"width":934,"height":935},"192","66","4","22",[62,937],{"x":127,"y":933,"width":934,"height":935},[62,939],{"x":940,"y":933,"width":934,"height":935},"216",[62,942],{"x":943,"y":933,"width":934,"height":935},"228",[62,945],{"x":946,"y":933,"width":934,"height":935},"240",[62,948],{"x":949,"y":933,"width":934,"height":935},"252",[62,951],{"x":952,"y":933,"width":934,"height":935},"264",[62,954],{"x":955,"y":933,"width":934,"height":935},"276",[62,957],{"x":958,"y":933,"width":934,"height":935},"288",[62,960],{"x":961,"y":933,"width":934,"height":935},"300",[62,963],{"x":964,"y":933,"width":934,"height":935},"312",[62,966],{"x":967,"y":933,"width":934,"height":935},"324",[62,969],{"x":970,"y":933,"width":934,"height":935},"336",[62,972],{"x":973,"y":933,"width":934,"height":935},"348",[62,975],{"x":976,"y":933,"width":934,"height":935},"360",[62,978],{"x":979,"y":933,"width":934,"height":935},"372",[62,981],{"x":982,"y":933,"width":934,"height":935},"384",[62,984],{"x":141,"y":933,"width":934,"height":935},[62,986],{"x":987,"y":933,"width":934,"height":935},"408",[62,989],{"x":990,"y":933,"width":934,"height":935},"420",[62,992],{"x":993,"y":933,"width":934,"height":935},"432",[62,995],{"x":996,"y":933,"width":934,"height":935},"444",[62,998],{"x":999,"y":933,"width":934,"height":935},"456",[62,1001],{"x":1002,"y":933,"width":934,"height":935},"468",[62,1004],{"x":1005,"y":933,"width":934,"height":935},"480",[62,1007],{"x":1008,"y":933,"width":934,"height":935},"492",[62,1010],{"x":1011,"y":933,"width":934,"height":935},"504",[62,1013],{"x":1014,"y":933,"width":934,"height":935},"516",[62,1016],{"x":1017,"y":933,"width":934,"height":935},"528",[62,1019],{"x":1020,"y":933,"width":934,"height":935},"540",[62,1022],{"x":1023,"y":933,"width":934,"height":935},"552",[62,1025],{"x":1026,"y":933,"width":934,"height":935},"564",[62,1028],{"x":1029,"y":933,"width":934,"height":935},"576",[62,1031],{"x":161,"y":933,"width":934,"height":935},[62,1033],{"x":1034,"y":933,"width":934,"height":935},"600",[62,1036],{"x":1037,"y":933,"width":934,"height":935},"612",[62,1039],{"x":1040,"y":933,"width":934,"height":935},"624",[62,1042],{"x":1043,"y":933,"width":934,"height":935},"636",[62,1045],{"x":1046,"y":933,"width":934,"height":935},"648",[62,1048],{"x":1049,"y":933,"width":934,"height":935},"660",[62,1051],{"x":1052,"y":933,"width":934,"height":935},"672",[62,1054],{"x":1055,"y":933,"width":934,"height":935},"684",[62,1057],{"x":1058,"y":933,"width":934,"height":935},"696",[62,1060],{"x":1061,"y":933,"width":934,"height":935},"708",[62,1063],{"x":1064,"y":933,"width":934,"height":935},"720",[86,1066,1069],{"x":180,"y":1067,"style":924,"fill":1068,"textAnchor":925},"142","#15803d","canvasReleaseEvent",[62,1071],{"x":1072,"y":1073,"width":76,"height":935,"fill":1068},"452","126",[62,1075],{"x":932,"y":180,"width":952,"height":1076,"rx":76,"fill":101,"stroke":102,"style":198},"52",[86,1078,1081],{"x":967,"y":1079,"style":1080,"fill":102,"textAnchor":92},"198","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","keep trivial",[86,1083,1085],{"x":967,"y":1084,"style":112,"fill":113,"textAnchor":92},"217","a conversion and a status update",[62,1087],{"x":1088,"y":180,"width":952,"height":1076,"rx":76,"fill":101,"stroke":1068,"style":198},"472",[86,1090,1092],{"x":1091,"y":1079,"style":1080,"fill":1068,"textAnchor":92},"604","can afford real work",[86,1094,1095],{"x":1091,"y":1084,"style":112,"fill":113,"textAnchor":92},"a spatial query or a dialog",[246,1097,1099],{"className":248,"code":1098,"language":250,"meta":251,"style":251},"class CoordinateReadoutTool(QgsMapTool):\n    def __init__(self, canvas, iface):\n        super().__init__(canvas)\n        self.canvas = canvas\n        self.iface = iface\n        project = QgsProject.instance()\n        self.to_wgs84 = QgsCoordinateTransform(\n            project.crs(), QgsCoordinateReferenceSystem(\"EPSG:4326\"), project\n        )\n\n    def canvasMoveEvent(self, event):\n        point = self.toMapCoordinates(event.pos())\n        geo = self.to_wgs84.transform(point)\n        self.iface.statusBarIface().showMessage(\n            f\"lat {geo.y():.5f}  lon {geo.x():.5f}\"\n        )\n",[23,1100,1101,1114,1123,1133,1143,1155,1164,1176,1186,1191,1195,1204,1215,1227,1234,1265],{"__ignoreMap":251},[255,1102,1103,1105,1108,1110,1112],{"class":178,"line":257},[255,1104,485],{"class":260},[255,1106,1107],{"class":320}," CoordinateReadoutTool",[255,1109,334],{"class":264},[255,1111,493],{"class":320},[255,1113,496],{"class":264},[255,1115,1116,1118,1120],{"class":178,"line":274},[255,1117,501],{"class":260},[255,1119,504],{"class":330},[255,1121,1122],{"class":264},"(self, canvas, iface):\n",[255,1124,1125,1127,1129,1131],{"class":178,"line":281},[255,1126,512],{"class":330},[255,1128,515],{"class":264},[255,1130,518],{"class":330},[255,1132,521],{"class":264},[255,1134,1135,1137,1139,1141],{"class":178,"line":293},[255,1136,526],{"class":330},[255,1138,529],{"class":264},[255,1140,287],{"class":260},[255,1142,534],{"class":264},[255,1144,1145,1147,1150,1152],{"class":178,"line":304},[255,1146,526],{"class":330},[255,1148,1149],{"class":264},".iface ",[255,1151,287],{"class":260},[255,1153,1154],{"class":264}," iface\n",[255,1156,1157,1160,1162],{"class":178,"line":309},[255,1158,1159],{"class":264},"        project ",[255,1161,287],{"class":260},[255,1163,749],{"class":264},[255,1165,1166,1168,1171,1173],{"class":178,"line":314},[255,1167,526],{"class":330},[255,1169,1170],{"class":264},".to_wgs84 ",[255,1172,287],{"class":260},[255,1174,1175],{"class":264}," QgsCoordinateTransform(\n",[255,1177,1178,1181,1183],{"class":178,"line":327},[255,1179,1180],{"class":264},"            project.crs(), QgsCoordinateReferenceSystem(",[255,1182,762],{"class":340},[255,1184,1185],{"class":264},"), project\n",[255,1187,1188],{"class":178,"line":373},[255,1189,1190],{"class":264},"        )\n",[255,1192,1193],{"class":178,"line":378},[255,1194,278],{"emptyLinePlaceholder":277},[255,1196,1197,1199,1202],{"class":178,"line":383},[255,1198,501],{"class":260},[255,1200,1201],{"class":320}," canvasMoveEvent",[255,1203,560],{"class":264},[255,1205,1206,1209,1211,1213],{"class":178,"line":389},[255,1207,1208],{"class":264},"        point ",[255,1210,287],{"class":260},[255,1212,592],{"class":330},[255,1214,595],{"class":264},[255,1216,1217,1220,1222,1224],{"class":178,"line":563},[255,1218,1219],{"class":264},"        geo ",[255,1221,287],{"class":260},[255,1223,592],{"class":330},[255,1225,1226],{"class":264},".to_wgs84.transform(point)\n",[255,1228,1229,1231],{"class":178,"line":578},[255,1230,526],{"class":330},[255,1232,1233],{"class":264},".iface.statusBarIface().showMessage(\n",[255,1235,1236,1239,1242,1244,1246,1249,1251,1254,1256,1258,1260,1262],{"class":178,"line":584},[255,1237,1238],{"class":260},"            f",[255,1240,1241],{"class":340},"\"lat ",[255,1243,344],{"class":330},[255,1245,817],{"class":264},[255,1247,1248],{"class":260},":.5f",[255,1250,353],{"class":330},[255,1252,1253],{"class":340},"  lon ",[255,1255,344],{"class":330},[255,1257,829],{"class":264},[255,1259,1248],{"class":260},[255,1261,353],{"class":330},[255,1263,1264],{"class":340},"\"\n",[255,1266,1267],{"class":178,"line":598},[255,1268,1190],{"class":264},[14,1270,1271,1273,1274,1276,1277,1280],{},[216,1272,397],{}," The transform lives on the instance, built once, because constructing a ",[23,1275,170],{}," involves resolving a datum path and is far too expensive to repeat sixty times a second. ",[23,1278,1279],{},"showMessage()"," overwrites the previous message rather than appending, which is what makes it suitable for a live readout. Anything heavier than this — a spatial query, a provider read — belongs in the click handler, not the move handler.",[205,1282,1284],{"id":1283},"format-coordinates-the-way-readers-expect","Format coordinates the way readers expect",[14,1286,1287],{},"A raw pair of floats is rarely what a user wants to see or copy. The convention differs by coordinate system, and getting it wrong makes a plugin feel unfinished even when the numbers are correct.",[14,1289,1290],{},[47,1291,1294,1297,1300,1303,1306,1311,1317,1322,1327,1332,1335,1339,1342,1345,1348,1351,1355,1358,1361,1364,1368,1372,1375],{"viewBox":1292,"role":50,"ariaLabel":1293,"xmlns":52},"0 0 760 250","The same position formatted four ways: raw decimal degrees, degrees minutes seconds, projected metres with thousands separators, and a copyable lat comma lon pair",[54,1295,1296],{},"Four presentations of the same position",[58,1298,1299],{},"One location is shown formatted four ways. Raw decimal degrees carry excessive precision. Degrees, minutes and seconds suit navigation and survey contexts. Projected metres with thousands separators and no decimals suit engineering. A latitude comma longitude pair with six decimals is the form users paste into other tools.",[62,1301],{"x":64,"y":64,"width":65,"height":1302,"fill":67},"250",[86,1304,1305],{"x":88,"y":89,"style":90,"fill":91,"textAnchor":92},"Same point, four audiences",[62,1307],{"x":1308,"y":1309,"width":1310,"height":1309,"rx":76,"fill":101,"stroke":197,"style":198},"16","46","728",[86,1312,1316],{"x":1313,"y":1314,"style":1315,"fill":197},"36","68","font-size:11.5px;font-weight:bold;font-family:sans-serif","raw",[86,1318,1321],{"x":1319,"y":1314,"style":1320,"fill":113},"130","font-size:12px;font-family:monospace","12.492373947, 41.890210043",[86,1323,1326],{"x":1324,"y":1314,"style":1325,"fill":113},"440","font-size:11px;font-family:sans-serif","nanometre precision on a mouse click",[86,1328,1331],{"x":1319,"y":1329,"style":1330,"fill":197},"84","font-size:10.5px;font-family:sans-serif","implies accuracy the data does not have",[62,1333],{"x":1308,"y":1334,"width":1310,"height":1309,"rx":76,"fill":101,"stroke":102,"style":198},"102",[86,1336,1338],{"x":1313,"y":1337,"style":1315,"fill":102},"124","DMS",[86,1340,1341],{"x":1319,"y":1337,"style":1320,"fill":113},"41°53'24.8\"N  12°29'32.5\"E",[86,1343,1344],{"x":1324,"y":1337,"style":1325,"fill":113},"navigation, survey, aviation",[86,1346,1347],{"x":1319,"y":153,"style":1330,"fill":123},"latitude first, hemisphere letters",[62,1349],{"x":1308,"y":1350,"width":1310,"height":1309,"rx":76,"fill":101,"stroke":163,"style":198},"158",[86,1352,1354],{"x":1313,"y":1353,"style":1315,"fill":163},"180","metres",[86,1356,1357],{"x":1319,"y":1353,"style":1320,"fill":113},"789 038 E   4 641 418 N",[86,1359,1360],{"x":1324,"y":1353,"style":1325,"fill":113},"engineering and cadastral work",[86,1362,1363],{"x":1319,"y":194,"style":1330,"fill":123},"no decimals, grouped thousands",[62,1365],{"x":1308,"y":1366,"width":1310,"height":1367,"rx":76,"fill":101,"stroke":1068,"style":198},"214","30",[86,1369,1371],{"x":1313,"y":1370,"style":1315,"fill":1068},"234","copyable",[86,1373,1374],{"x":1319,"y":1370,"style":1320,"fill":113},"41.890210, 12.492374",[86,1376,1377],{"x":1324,"y":1370,"style":1325,"fill":113},"pastes into any other tool",[14,1379,1380],{},"QGIS has the conversion built in, so there is no need to write degree arithmetic:",[246,1382,1384],{"className":248,"code":1383,"language":250,"meta":251,"style":251},"from qgis.core import QgsCoordinateFormatter, Qgis\n\n\ndef describe(point, crs):\n    if crs.isGeographic():\n        return QgsCoordinateFormatter.format(\n            point, Qgis.CoordinateOrder.YX, precision=1,\n            flags=QgsCoordinateFormatter.FlagDegreesUseStringSuffix,\n            format=Qgis.CoordinateDisplayType.MinutesSeconds,\n        )\n    return f\"{point.x():,.0f} E   {point.y():,.0f} N\"\n",[23,1385,1386,1397,1401,1405,1415,1423,1431,1453,1463,1473,1477],{"__ignoreMap":251},[255,1387,1388,1390,1392,1394],{"class":178,"line":257},[255,1389,261],{"class":260},[255,1391,444],{"class":264},[255,1393,268],{"class":260},[255,1395,1396],{"class":264}," QgsCoordinateFormatter, Qgis\n",[255,1398,1399],{"class":178,"line":274},[255,1400,278],{"emptyLinePlaceholder":277},[255,1402,1403],{"class":178,"line":281},[255,1404,278],{"emptyLinePlaceholder":277},[255,1406,1407,1409,1412],{"class":178,"line":293},[255,1408,317],{"class":260},[255,1410,1411],{"class":320}," describe",[255,1413,1414],{"class":264},"(point, crs):\n",[255,1416,1417,1420],{"class":178,"line":304},[255,1418,1419],{"class":260},"    if",[255,1421,1422],{"class":264}," crs.isGeographic():\n",[255,1424,1425,1428],{"class":178,"line":309},[255,1426,1427],{"class":260},"        return",[255,1429,1430],{"class":264}," QgsCoordinateFormatter.format(\n",[255,1432,1433,1436,1439,1441,1445,1447,1450],{"class":178,"line":314},[255,1434,1435],{"class":264},"            point, Qgis.CoordinateOrder.",[255,1437,1438],{"class":330},"YX",[255,1440,356],{"class":264},[255,1442,1444],{"class":1443},"s9osk","precision",[255,1446,287],{"class":260},[255,1448,1449],{"class":330},"1",[255,1451,1452],{"class":264},",\n",[255,1454,1455,1458,1460],{"class":178,"line":327},[255,1456,1457],{"class":1443},"            flags",[255,1459,287],{"class":260},[255,1461,1462],{"class":264},"QgsCoordinateFormatter.FlagDegreesUseStringSuffix,\n",[255,1464,1465,1468,1470],{"class":178,"line":373},[255,1466,1467],{"class":1443},"            format",[255,1469,287],{"class":260},[255,1471,1472],{"class":264},"Qgis.CoordinateDisplayType.MinutesSeconds,\n",[255,1474,1475],{"class":178,"line":378},[255,1476,1190],{"class":264},[255,1478,1479,1482,1485,1487,1489,1491,1494,1496,1499,1501,1503,1505,1507],{"class":178,"line":383},[255,1480,1481],{"class":260},"    return",[255,1483,1484],{"class":260}," f",[255,1486,341],{"class":340},[255,1488,344],{"class":330},[255,1490,347],{"class":264},[255,1492,1493],{"class":260},":,.0f",[255,1495,353],{"class":330},[255,1497,1498],{"class":340}," E   ",[255,1500,344],{"class":330},[255,1502,361],{"class":264},[255,1504,1493],{"class":260},[255,1506,353],{"class":330},[255,1508,1509],{"class":340}," N\"\n",[14,1511,1512,398,1514,1517,1518,1521,1522,1524,1525,1528,1529,1531],{},[216,1513,397],{},[23,1515,1516],{},"QgsCoordinateFormatter"," produces the degrees-minutes-seconds form with the hemisphere suffixes, matching what QGIS's own status bar shows. ",[23,1519,1520],{},"CoordinateOrder.YX"," puts latitude first, which is the convention for geographic display even though ",[23,1523,405],{}," stores x first. Branching on ",[23,1526,1527],{},"crs.isGeographic()"," means one function serves both cases without the caller deciding. The ",[23,1530,1493],{}," format on the projected branch groups thousands and drops the decimals, because a click is never accurate to the millimetre and showing decimals implies otherwise.",[205,1533,1535],{"id":1534},"qgis-version-compatibility","QGIS version compatibility",[14,1537,1538,1539,1541],{},"The examples target ",[216,1540,218],{}," (Python 3.12).",[1543,1544,1545,1561],"table",{},[1546,1547,1548],"thead",{},[1549,1550,1551,1555,1558],"tr",{},[1552,1553,1554],"th",{},"QGIS version",[1552,1556,1557],{},"Python",[1552,1559,1560],{},"Notes",[1562,1563,1564,1580,1591],"tbody",{},[1549,1565,1566,1570,1573],{},[1567,1568,1569],"td",{},"3.28 LTR",[1567,1571,1572],{},"3.9",[1567,1574,1575,1576,1579],{},"Identical API. ",[23,1577,1578],{},"statusBarIface()"," available throughout 3.x.",[1549,1581,1582,1585,1588],{},[1567,1583,1584],{},"3.34 LTR",[1567,1586,1587],{},"3.12",[1567,1589,1590],{},"Baseline for this page.",[1549,1592,1593,1596,1598],{},[1567,1594,1595],{},"3.40 \u002F 3.44",[1567,1597,1587],{},[1567,1599,1600,1603],{},[23,1601,1602],{},"QgsMapToolEmitPoint.canvasClicked"," signature unchanged; coordinate helpers unchanged.",[14,1605,1606,356,1608,1610,1611,1613],{},[23,1607,25],{},[23,1609,150],{}," and ",[23,1612,243],{}," have been stable across the whole 3.x line.",[205,1615,1617],{"id":1616},"troubleshooting","Troubleshooting",[210,1619,1620,1634,1643,1659,1665,1671],{},[213,1621,1622,1625,1626,1628,1629,1631,1632,234],{},[216,1623,1624],{},"Coordinates are enormous or negative."," Pixel positions were used directly. ",[23,1627,108],{}," must go through ",[23,1630,25],{}," or ",[23,1633,150],{},[213,1635,1636,1639,1640,234],{},[216,1637,1638],{},"The click never matches a feature."," The coordinates are in the canvas CRS and the layer is in another. Use ",[23,1641,1642],{},"toLayerCoordinates(layer, event.pos())",[213,1644,1645,398,1648,1650,1651,1654,1655,1658],{},[216,1646,1647],{},"Latitude and longitude look swapped.",[23,1649,405],{}," stores x first, which is longitude. Print ",[23,1652,1653],{},"y()"," before ",[23,1656,1657],{},"x()"," when reporting a geographic position.",[213,1660,1661,1664],{},[216,1662,1663],{},"The readout is jerky."," The move handler is doing too much — most often rebuilding the coordinate transform on every event. Build it once in the constructor.",[213,1666,1667,1670],{},[216,1668,1669],{},"Nothing is emitted."," The tool object was collected. Keep a reference on the plugin instance.",[213,1672,1673,1676,1677,1680,1681,1684,1685,234],{},[216,1674,1675],{},"The right button triggers the action too."," Filter on ",[23,1678,1679],{},"event.button() == Qt.LeftButton",", or on the ",[23,1682,1683],{},"button"," argument of ",[23,1686,401],{},[205,1688,1690],{"id":1689},"conclusion","Conclusion",[14,1692,1693,1694,1696,1697,1699,1700,1702],{},"Capturing a click is a chain of coordinate spaces, and each conversion has a specific method: ",[23,1695,25],{}," for the canvas CRS, ",[23,1698,150],{}," for comparison against geometry, and a ",[23,1701,170],{}," built once for display. Get the chain right and everything downstream — identify, snapping, measurement — falls into place.",[205,1704,1706],{"id":1705},"frequently-asked-questions","Frequently Asked Questions",[14,1708,1709,1712,1715,1716,1718,1719,1721,1722,1724,1725,1727],{},[216,1710,1711],{},"Which method converts a click to map coordinates?",[23,1713,1714],{},"self.toMapCoordinates(event.pos())"," on a ",[23,1717,493],{},", which returns a ",[23,1720,405],{}," in the canvas CRS. ",[23,1723,243],{}," does the same conversion for you and hands the point to its ",[23,1726,401],{}," signal.",[14,1729,1730,1733,1734,1736],{},[216,1731,1732],{},"Why does my click never match a feature?","\nThe point is in the canvas CRS and the layer's geometry is in the layer's CRS. Use ",[23,1735,1642],{},", which applies both the pixel conversion and the CRS transform.",[14,1738,1739,1742,1743,1745,1746,1748,1749,1751],{},[216,1740,1741],{},"How do I show latitude and longitude when the project uses a projected CRS?","\nBuild a ",[23,1744,170],{}," from the project CRS to EPSG:4326 once, and transform each point before displaying it. Remember to print ",[23,1747,1653],{}," as latitude and ",[23,1750,1657],{}," as longitude.",[14,1753,1754,1757,1758,1760],{},[216,1755,1756],{},"Can I track the cursor without clicking?","\nYes — override ",[23,1759,926],{},". Keep it cheap: it fires on every mouse move, so build any coordinate transform in the constructor rather than in the handler.",[14,1762,1763,1766,1767,1770],{},[216,1764,1765],{},"How do I copy the clicked coordinate to the clipboard?","\nFormat it first, then use Qt's clipboard: ",[23,1768,1769],{},"QApplication.clipboard().setText(text)",". Copying the raw floats is rarely what a user wants — a latitude-comma-longitude pair with six decimals pastes cleanly into almost every other tool, which is why it is worth formatting rather than dumping.",[14,1772,1773,1776,1777,1779],{},[216,1774,1775],{},"Does the click coordinate account for map rotation?","\nYes. ",[23,1778,25],{}," uses the canvas's full transform, including any rotation set on the map. That is another reason to use it rather than computing the position from the pixel offset yourself, which would silently ignore rotation.",[14,1781,1782,1785,1786,1788],{},[216,1783,1784],{},"Can I capture a click without installing a map tool?","\nNot reliably. The canvas routes mouse events to its active tool, so intercepting them any other way means fighting the framework. Installing a lightweight ",[23,1787,243],{}," is the supported route and is only a few lines.",[14,1790,1791,1794],{},[216,1792,1793],{},"Does the canvas report coordinates while panning?","\nYes, continuously — which is another reason to keep move handlers cheap.",[14,1796,1797,1800,1801,1804,1805,1808],{},[216,1798,1799],{},"Can I restrict clicks to inside a particular layer's extent?","\nYes — convert the click, build a ",[23,1802,1803],{},"QgsRectangle"," from the layer extent and test ",[23,1806,1807],{},"contains()",". Rejecting clicks outside the data is friendlier than returning coordinates that cannot possibly match anything.",[205,1810,1812],{"id":1811},"related","Related",[210,1814,1815,1820,1824,1830],{},[213,1816,1817,1819],{},[39,1818,42],{"href":41}," — the guide this recipe belongs to",[213,1821,1822],{},[39,1823,425],{"href":424},[213,1825,1826],{},[39,1827,1829],{"href":1828},"\u002Fqgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002Fidentify-feature-under-cursor-pyqgis\u002F","Identify the Feature Under the Cursor in PyQGIS",[213,1831,1832],{},[39,1833,1835],{"href":1834},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Ftransform-point-coordinates-pyqgis\u002F","Transform Point Coordinates Between CRS in PyQGIS",[1837,1838,1839],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":251,"searchDepth":274,"depth":274,"links":1841},[1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852],{"id":207,"depth":274,"text":208},{"id":237,"depth":274,"text":238},{"id":428,"depth":274,"text":429},{"id":696,"depth":274,"text":697},{"id":898,"depth":274,"text":899},{"id":1283,"depth":274,"text":1284},{"id":1534,"depth":274,"text":1535},{"id":1616,"depth":274,"text":1617},{"id":1689,"depth":274,"text":1690},{"id":1705,"depth":274,"text":1706},{"id":1811,"depth":274,"text":1812},"Read the coordinates of a canvas click in PyQGIS with QgsMapToolEmitPoint, convert pixels to map and layer coordinates, and report positions in any CRS.","md",{"slug":1856,"type":1857,"breadcrumb":1858,"datePublished":1859,"dateModified":1859},"capture-map-click-coordinates-pyqgis","article","Capture Click Coordinates","2026-08-01","\u002Fqgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002Fcapture-map-click-coordinates-pyqgis",{"title":5,"description":1853},"qgis-plugin-development\u002Fcustom-map-tools-and-canvas-interaction\u002Fcapture-map-click-coordinates-pyqgis\u002Findex","FcX7KX93zX1MxZW0AYLy9d9q-gerIx2OzlF2dkIeTYs",1785585990473]