I have problems getting canvas.find_closest(x, y) to work properly. Below you can see a minimum working example. The program draws several points in the map (small radius ovals) and several horizontal and vertical lines to simulate a grid. When the user clicks on the map, a red 'X' is drawn in the element that is closest to the clicked coordinates (see 1). This works as expected. import tkinter as tk from tkinter import ttk class MapCanvas: def __init__(self, root): self.size = 600 self.root = root self.mainframe = ttk.Frame(self.root) self.canv = tk.Canvas(self.mainframe, width=self.size, height=self.size) self.canv.bind("<Motion>", self.update_coordinates) self.canv.bind("<Button-1>", self.find_nearest) self.status_bar = ttk.Frame(self.mainframe) self.lbl_status = ttk.Label(self.status_bar, relief=tk.GROOVE, text='Coordinates go here') # Draw some points in map self.draw_points(-150, 'blue', 'first_batch') self.draw_points(-20, 'black', 'second_batch') self.draw_lines() self.mainframe.pack() self.canv.pack() self.status_bar.pack(fill='both', expand=True) self.lbl_status.pack(side='left', fill='x', expand=True) def update_coordinates(self, event): x, y = event.x, event.y self.lbl_status.config(text=f"Mouse coordinates: ({x}, {y})") def find_nearest(self, event): # Get the mouse coordinates x, y = event.x, event.y closest = self.canv.find_closest(x, y) # (1) # Draw an 'X' in the closest element, as found by self.canv.find_closest() coords = self.canv.coords(closest[0]) # Center of the bounding box x, y = (coords[0] + coords[2]) / 2, (coords[1] + coords[3]) / 2 # Size of 'X' in map amount = 5 a1 = self.canv.create_line(x - amount, y - amount, x + amount, y + amount, fill='red') a2 = self.canv.create_line(x - amount, y + amount, x + amount, y - amount, fill='red') def draw_points(self, offset, fill, tags): for x in range(1, 4): for y in range(1, 4): id = self.canv.create_oval(x * 200 + offset - 1, y * 200 + offset - 1, x * 200 + offset + 1, y * 200 + offset + 1, fill=fill, tags=tags) print(tags, id) def draw_lines(self): for x in range(1, 4): id = self.canv.create_line( x * 200 + 10, 0, x * 200 + 10, 600, fill='green', tags='grid_lines') print(id) for y in range(1, 4): id = self.canv.create_line( 0, y * 200 + 10, 600, y * 200 + 10, fill='green', tags='grid_lines') print(id) if __name__ == '__main__': root = tk.Tk() mapcanvas = MapCanvas(root) root.mainloop() However, if I want to make the program draw the 'X' in the nearest oval, without considering the lines, I change (1) to closest = self.canv.find_closest(x, y, halo=0, start=9) # (2) because I know that the drawn points have ids from 1 to 9 ('first_batch') or from 10 to 18 ('second_batch'). Lines have ids from 19 to 24. According to the documentation, "If an object ID is passed in the start argument, this method tags the highest qualifying object that is below start in the display list." So I configure 'start' to 9 to find the closest point to the clicked coordinates but only searching in ids 1 to 9. However, this doesn't work because it finds the lines as the closest elements, if you click near enough. # print(self.canv.type(closest[0])) prints 'line', not 'oval' I thought maybe I had misunderstood how 'start' works, so I changed it to start=1, and I got the same results (also with start=18). I also tried with closest = self.canv.find_closest(x, y, halo=None, start=9) # (3) but it doesn't work either, so I got back to (2) because somewhere I read that, if 'start' is specified, 'halo' must be different from None. In the end, I made it work using a workaround, but it is a not very elegant solution and it muddles the code: # Move everything out of range so that the nearest point # to the clicked coordinates is always one of the 'first_batch' self.canv.move('grid_lines', 3000, 0) self.canv.move('second_batch', 3000, 0) # Find the closest point from 'first_batch' closest = self.canv.find_closest(x, y, halo=None, start=None) # Move lines and 'second_batch' points back to their original places self.canv.move('grid_lines', -3000, 0) self.canv.move('second_batch', -3000, 0) # Now I can draw the 'X' coords = self.canv.coords(closest[0]) # Center of the bounding box x, y = (coords[0] + coords[2]) / 2, (coords[1] + coords[3]) / 2 #self.canv.create_line(coords[0], coords[1], coords[2], coords[3], fill='red') #self.canv.create_line(coords[0], coords[3], coords[2], coords[1], fill='red') # Size of 'X' in map amount = 5 a1 = self.canv.create_line(x - amount, y - amount, x + amount, y + amount, fill='red') a2 = self.canv.create_line(x - amount, y + amount, x + amount, y - amount, fill='red') But there must be a way to make it work using 'halo' and 'start' properly. However, I don't know how. Another workaround is iterating through all 'first_batch' points, for item in self.canvas.find_withtag("first_batch"): then computing the Euclidean distance to the clicked coordinates and comparing that distance with a variable that holds the minimum distance... but it is a bit of a stretch, isn't it? Unless I have 'halo' and 'start' parameters totally wrong and they don't work the way I think. Thanks in advance. Continue reading...