pythontkinterbindframefocusout

Make frame disappear when it is not in focus


I'm trying to make a frame disappear when it is not in focus, as in, if the mouse is clicked anywhere but the frame, then the frame should disappear.

Like what a pop up menu does, although I don't want to use a pop up menu.

Here's the code:

from tkinter import *

root = Tk()
root.geometry('700x700')

b = Button(root, text='Show Frame',command=lambda: showlabel())
b.pack()
l = Frame(width=200,height=200,bg='black')
l.bind("<FocusOut>", l.pack_forget())


def showlabel():
    l.pack()


root.mainloop()

Solution

  • <FocusOut> refers to keyboard focus. It sounds like that's not what you mean, however, since frames don't typically have keyboard focus.

    If you are trying to emulate a popup window or message box, one way would be to add a grab on the window, and a binding that detects when you click outside the window.

    A grab is a way to focus all events to a window and it's children. This is handy because you don't want the user to interact with widgets outside of your popup window while it is visible. For example, you don't want a click on the Show Frame button to open another window if the window is already visible.

    Once you've created the frame, you can call grab_set on the frame. You can then add a binding on the frame, and the binding will fire even when the user clicks outside the frame. In the binding you can check to see whether the binding is inside or outside, and hide the window if the click is outside.

    The solution looks something like this:

    def showlabel():
        def dismiss(event):
            if not ((0 <= event.x <= l.winfo_width()) and (0 <= event.y <= l.winfo_height())):
                l.grab_release()
                l.pack_forget()
    
        l.pack(pady=20)
        l.bind("<1>", dismiss)
        l.grab_set()
    

    This would be better to implement as a class, but this gives a general idea.