Tk / Tkinter: detecting lost application focus

I am making a Tkinter application. In the application, I want to open the context menu that I use with Tk.Menu.post ().

I do not know how to make this menu disappear when the application loses focus. I need to do this because the menu stays on top, even when switching to another window, leaving the menu β€œartifact”.

I place a <FocusOut> event on the menu that fires if the menu has focus and the user moves the focus to another application. It works well.

What if the main application window has focus? I can put the <FocusOut> event in an application window that closes the menu; however, this ends up being called when I focus on the menu that closes the menu. The menu is created with the parent as the main application, so I'm not sure why <FocusOut> in the main application even starts when the menu receives focus.

How to distinguish the main application window from focus with another application and lose focus in my menu?

I do not want to use tk_popup () because I want the user to continue to provide input to the main window. (use of the menu is optional).

Thanks to @Brad Lanam, I came up with a SOLUTION in which I included:

 from Tkinter import * class App(Tk): def __init__(self, *args, **kwargs): Tk.__init__(self, *args, **kwargs) self.entry = Entry(self) self.entry.grid(padx=30, pady=30) self.entry.focus_set() self.entry.bind("<Tab>", self.put_menu) self.entry.bind("<Down>", self.set_focus_on_menu) self.menu = Menu(self, tearoff=False) self.menu.add_command(label="test") self.menu.bind("<FocusOut>", self.destroy_menu) self.bind("<FocusIn>", self.app_got_focus) self.bind("<FocusOut>", self.app_lost_focus) self.bind("<3>", self.put_menu) def app_got_focus(self, event): self.config(background="red") def app_lost_focus(self, event): self.config(background="grey") ######## SOLUTION BEGIN ######### if self.focus_get() != self.menu: self.destroy_menu(event) ######## SOLUTION END ########### def set_focus_on_menu(self, event): self.menu.focus_set() def menu_got_focus(self, event): self.menu.activate(0) def put_menu(self, event): self.menu.post(self.winfo_x() + self.entry.winfo_x(), self.winfo_y() + self.entry.winfo_y()+20) def destroy_menu(self, event): self.menu.destroy() app = App() app.mainloop() 
+4
source share
1 answer

self.focus_get () will return an object with focus, which can be used to distinguish the focus receiving the menu from another application.

For example, to remove a menu when focus moves to another application:

 def app_lost_focus(self, event): if self.focus_get() != self.menu: self.destroy_menu(event) 
+2
source

Source: https://habr.com/ru/post/1495606/


All Articles