Search code examples
pythontkintercanvasobjectid

How can I get the object id of a tkinter canvas item built by a self-defined class?


I have defined the class state, which consists out of two tkinter canvas items. After adding an instance of this class to a tkinter canvas, I want to identify the instance by the left mouse button. I have used the canvas find_overlapping-method for this. But of course I only get the canvas item id of the instance instead of the object id (which I need for calling methods on the instances of the class state). How can I derive the object id from the canvas item id? Please look into this example:

from tkinter import *  

class state():
    def __init__(self, canvas, x_position, y_position, *args, **kwargs):
        self.oval = canvas.create_oval(x_position-20, y_position-20, x_position+20, y_position+20, fill='cyan')
        self.text = canvas.create_text(x_position, y_position, text='S1')

x, y= 40, 40
def insert_state(canvas):
    global x, y
    global id
    id = state(canvas, x, y)
    x += 40
    y += 40

def identify(event, canvas):
    canvas_item_id = canvas.find_overlapping(event.x,event.y,event.x,event.y)
    print("Found canvas item with id ", canvas_item_id)

root = Tk()
canvas = Canvas(root)
canvas.grid()
button1 = Button(root, text='add state')
button1.grid()
button1.bind('<Button-1>', lambda event, canvas=canvas : insert_state (canvas))
canvas.bind ('<Button-1>', lambda event, canvas=canvas : identify     (event, canvas))

root.mainloop()

Solution

  • Following the comment of acw1668, I have solved the problem: I added a dictionary as a class variable. At any time when a new instance of the class is created, the dictionary gets a new entry. Each entry has as key the Canvas Item ID. The value of each entry is the reference of the instance. So by looking into this dictionary I am able to convert Canvas Item IDs into references and afterwards I can call methods for each reference (my example has no such methods in order to keep it simple). Sorry for perhaps being not so exact in my explanation, I am new to SW development.

    Updated code:

    from tkinter import *  
    
    class state():
        state_dict = {} # NEW DICTIONARY
        def __init__(self, canvas, x_position, y_position, *args, **kwargs):
            self.oval = canvas.create_oval(x_position-20, y_position-20, x_position+20, y_position+20, fill='cyan')
            self.text = canvas.create_text(x_position, y_position, text='S1')
            state.state_dict[self.oval] = self # NEW ENTRY TO THE DICTIONARY
    
    x, y= 40, 40
    def insert_state(canvas):
        global x, y
        global id
        id = state(canvas, x, y)
        x += 40
        y += 40
    
    def identify(event, canvas):
        canvas_item_id = canvas.find_overlapping(event.x,event.y,event.x,event.y)
        print("Found canvas item with id ", canvas_item_id[0])
        print("Found reference ", state.state_dict[canvas_item_id[0]]) # SOLVED
    
    root = Tk()
    canvas = Canvas(root)
    canvas.grid()
    button1 = Button(root, text='add state')
    button1.grid()
    button1.bind('<Button-1>', lambda event, canvas=canvas : insert_state (canvas))
    canvas.bind ('<Button-1>', lambda event, canvas=canvas : identify     (event, canvas))
    
    root.mainloop()