Tk/Tkinter: Detect application lost focus

心已入冬 提交于 2019-12-10 14:59:02

问题


I am making a Tkinter application. In the application, I want to pop up a context menu, which I do using Tk.Menu.post().

I don't 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 a menu 'artifact'.

I put a <FocusOut> event on the menu, which is triggered if the menu has focus and the user moves focus to another application. This works well.

What do I do if the main application window has focus? I could put a <FocusOut> event on the application window, which closes the menu; however, this ends up being called when I give focus to the menu, which closes the menu. The menu is created with parent as the main application, so I am not sure why <FocusOut> on the main app is even triggered when the menu gets focus.

How do I distinguish between the main application window losing focus to a different application vs losing focus to my menu?

I don't 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, which I have 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()

回答1:


self.focus_get() will return the object that has focus, which can be used to distinguish between the menu receiving focus, vs some other application.

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

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


来源:https://stackoverflow.com/questions/18089068/tk-tkinter-detect-application-lost-focus

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!