Tkinter Toplevel : Destroy window when not focused
I had a similar problem, and fixed it. The following example works fine.It displays a Toplevel window on top of the main window, as a customized config menu.Whenever the user clicks somewhere else, the config menu disappears.
Warning: Don't use .transient(parent) on the Toplevel window, otherwise, the symptom that you described happens: when clicking on the main window, the menu does not disappear. You can try in the example below to uncomment the "self.transient(parent)" line to reproduce your issue.
Example:
import Tixclass MainWindow(Tix.Toplevel): def __init__(self, parent): # Init self.parent = parent Tix.Toplevel.__init__(self, parent) self.protocol("WM_DELETE_WINDOW", self.destroy) w = Tix.Button(self, text="Config menu", command=self.openMenu) w.pack() def openMenu(self): configWindow = ConfigWindow(self) configWindow.focus_set()class ConfigWindow(Tix.Toplevel): def __init__(self, parent): # Init self.parent = parent Tix.Toplevel.__init__(self, parent) # If you uncomment this line it reproduces the issue you described #self.transient(parent) # Hides the window while it is being configured self.withdraw() # Position the menu under the mouse x = self.parent.winfo_pointerx() y = self.parent.winfo_pointery() self.geometry("+%d+%d" % (x, y)) # Configure the window without borders self.update_idletasks() # Mandatory for .overrideredirect() method self.overrideredirect(True) # Binding to close the menu if user does something else self.bind("<FocusOut>", self.close) # User focus on another window self.bind("<Escape>", self.close) # User press Escape self.protocol("WM_DELETE_WINDOW", self.close) # The configuration items w = Tix.Checkbutton(self, text="Config item") w.pack() # Show the window self.deiconify() def close(self, event=None): self.parent.focus_set() self.destroy()tixRoot = Tix.Tk()tixRoot.withdraw()app = MainWindow(tixRoot)app.mainloop()
The other solutions didn't work for me when I had 2 <tkinter.Entry>
s but I found this:
import tkinter as tkfocus = 0def focus_in(event): global focus focus += 1def focus_out(event): global focus focus -= 1 if focus == 0: root.destroy()root = tk.Toplevel()root.bind("<FocusIn>", focus_in)root.bind("<FocusOut>", focus_out)root.mainloop()
It has a counter for the number of times the window is focused. It destroys the window when the counter reaches 0.