Home > database >  tkinter get widget that event got called by
tkinter get widget that event got called by

Time:11-12

Minimal reproducable Example

from tkinter import *

def test(event):
    print(event.widget)

window = Tk()
window.geometry("600x600")
window.bind("<Motion>", test)

frame = Frame(window, bg="red", width=200, height=200)
frame.pack()
frame.bind("<Motion>", test)

window.mainloop()

I want to call the function "test" from different widgets when i move over them. Instead of that, when i hover over the frame, both the window and the frame print that im hovering over the frame, which is not the behaviour i need. Can someone help me achieve the right behaviour?

CodePudding user response:

I think your confusion is in the moment of interpreting when the mouse pointer entered the widget or left the widget. Instead of Motion let's use for example Leave and Enter events to better understand what happens.

I have taken the liberty of including some labels that show which widget we enter and left at each moment.

from tkinter import *

def test_enter(event):
    enter.set(event.widget)

def test_left(event):
    left.set(event.widget)

window = Tk()
window.geometry("300x300")
window.bind("<Enter>", test_enter)
window.bind("<Leave>", test_left)

frame = Frame(window, bg="red", width=200, height=200)
frame.pack()
frame.bind("<Enter>", test_enter)
frame.bind("<Leave>", test_left)

label1 = Label(frame, text="Enter")
label1.place(relx=0.1, rely=0.4, x= 0.2, y=0.2)
enter = StringVar()
label_enter = Label(frame, textvariable=enter)
label_enter.place(relx=0.3, rely=0.4, x= 0.6, y=0.2)

label2 = Label(frame, text="Leave")
label2.place(relx=0.1, rely=0.6, x= 0.2, y=0.2)
left = StringVar()
label_left = Label(frame, textvariable=left)
label_left.place(relx=0.3, rely=0.6, x= 0.6, y=0.2)

window.mainloop()

Remember that the Frame is inside the Window. I mean that when you enter the Window you have not left root Window, you will continue to be in Window. Or if you enter inside a Label you have not left the Frame.

CodePudding user response:

You could use lambda to pass the widget when the function is run


def test(event, widget):
    print(widget)

window = Tk()
window.geometry("600x600")
window.bind("<Motion>", test)

frame = Frame(window, bg="red", width=200, height=200)
frame.pack()
frame.bind("<Motion>", lambda: test(frame))

window.mainloop()

You just need to change two lines

def test(event, widget):
    print(widget)

and

frame.bind("<Motion>", lambda: test(frame))
  • Related