I want to find which Canvas
item is closer to the point I clicked. I am trying to use find the closest but I can't use it efficiently. I am trying to make an itemlist
and then find which item is the closest in the itemlist
. I also have self
keywords since I'm trying to do all this using classes
def initUI(self):
self.canvas = Canvas(self.parent)
self.item1 = self.canvas.create_oval(50, 50, 60, 60, fill="red")
self.item2 = self.canvas.create_oval(100, 100, 110, 110, fill="red")
self.item3 = self.canvas.create_oval(150, 150, 160, 160, fill="red")
self.itemlist = []
self.itemlist.append(self.item1)
self.itemlist.append(self.item2)
self.itemlist.append(self.item3)
print(self.itemlist)
self.canvas.pack()
self.canvas.bind("<Button-1>", self.find_closest)
def find_closest(self, event):
""" """
CodePudding user response:
As pointed out in the comments you can use the Canvas method find_closest()
to do what's needed. Below is a runnable example of doing that based on the code in your question. It uses an auxilary dictionary to map the ids of the canvas object to arbitrary strings (referred to as "names" in the example).
import tkinter as tk
from tkinter.constants import *
class MyClass:
def __init__(self, parent):
self.parent = parent
self.initUI()
def initUI(self):
self.canvas = tk.Canvas(self.parent)
self.canvas.pack()
self.canvas.bind("<Button-1>", self.find_closest)
# Create dictionary mapping canvas object ids to a name.
self.object_names = {}
id = self.canvas.create_oval(50, 50, 60, 60, fill="Red")
self.object_names[id] = 'Red object'
id = self.canvas.create_oval(100, 100, 110, 110, fill="Blue")
self.object_names[id] = 'Blue object'
id = self.canvas.create_oval(150, 150, 160, 160, fill="Green")
self.object_names[id] = 'Green object'
self.name_lbl1 = tk.Label(self.parent, text='Closest object:')
self.name_lbl1.pack(side=LEFT)
self.name_var = tk.StringVar(value='')
self.name_lbl2 = tk.Label(self.parent, textvariable=self.name_var)
self.name_lbl2.pack(side=LEFT)
def find_closest(self, event):
if (closest := self.canvas.find_closest(event.x, event.y)):
obj_id = closest[0]
self.name_var.set(self.object_names[obj_id]) # Updates lbl2.
if __name__ == '__main__':
root = tk.Tk()
instance = MyClass(root)
root.mainloop()
Screenshot of it running: