Kvothe
Kvothe

Reputation: 1837

Detecting `<Enter>` and `<Leave>` events for a frame in tkinter

I have a menu which when the user moves their mouse off I want to disappear. The menu consists of a Frame packed with several Label/Button widgets. I can detect the user moving their mouse off a Label/Button with simply binding to the <Enter>/<Leave events for those. But binding to the same events for the frame never triggers - I guess because the widgets on top cover up the frame so the mouse never enters it?

Is their a way to make the events propagate down to the containing Frame?

window=tkinter.Tk()
menu_frm = tkinter.Frame(window, name="menu_frm")
lbl_1 = tkinter.Label(menu_frm, text="Label", name="lbl_1")
lbl_1.pack()
lbl_2 = tkinter.Label(menu_frm, text="Label", name="lbl_2")
lbl_2.pack()
menu_frm.pack()
# These two (per label and the number of labels is likely to grow) events fire
lbl_1.bind("<Enter>", lambda _: stayopenfunction())
lbl_1.bind("<Leave>", lambda _: closefunction())
lbl_2.bind("<Enter>", lambda _: stayopenfunction())
lbl_2.bind("<Leave>", lambda _: closefunction())
# These two events do not fire
menu_frm.bind("<Enter>", lambda _: stayopenfunction())
menu_frm.bind("<Leave>", lambda _: closefunction())

Upvotes: 2

Views: 6236

Answers (2)

user7834224
user7834224

Reputation:

I found an easy fix for what your trying to do, I was trying to do the same!

def function2(event):
    -revert event-
    Widget.bind("<Enter>", function1)
def function1(event):
    -hover event-
    Widget.bind("<Leave>", function2)
Widget.bind("<Enter>", function1)

Its a bit stupid, its not the best, but it just means that when you hover it does what its meant to and then listens for the event that reverts it, in this case ''.

Upvotes: 1

saulspatz
saulspatz

Reputation: 5261

If you're just trying to simplify maintenance of the callbacks on the widgets, then I don't think binding events to the containing frame is the best approach. (I guess it's possible to generate virtual events in the callbacks on the buttons and labels, and bind the virtual event to the frame, but it seems rather complicated. Maybe that's just because I have no experience with virtual events.)

Why not just subclass the label and button widgets? Look at the "Instance and Class Bindings" heading at http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm Then you'd just have two class binding to maintain, one for the labels and one for the buttons. This seems cleaner to me; it's just vanilla OOP.

Hope this helps.

Upvotes: 0

Related Questions