Matthias Schweikart
Matthias Schweikart

Reputation: 707

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()

Upvotes: 0

Views: 2688

Answers (1)

Matthias Schweikart
Matthias Schweikart

Reputation: 707

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()

Upvotes: 1

Related Questions