Tkinter main window focus

后端 未结 6 653
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-09 10:36

I have the following code

window = Tk()
window.lift()
window.attributes(\"-topmost\", True)

This co

相关标签:
6条回答
  • 2020-12-09 10:46

    Note: this is Windows specific. This focuses the whole main window. Essentially forcing an alt-tab to reach the window.


    None of these answers worked for me, the tk window would appear on top of everything with the -topmost flag, my input box would have focus, but the window itself wouldn't, which meant that typing wouldn't appear in the tk window. It looks like like this:

    What helped was adding a call to the Windows API to steal focus:

    import win32gui    
    root = tk.Tk()
    
    # Application specific setup ...
    
    win32gui.SetForegroundWindow(root.winfo_id())
    

    Disclaimer: Stealing focus is bad behaviour, so only use it if you must and if it makes sense, e.g. input box the user will instantly type into.

    0 讨论(0)
  • 2020-12-09 10:53

    If focus_force() is not working you can try doing:

    window.after(1, lambda: window.focus_force())
    

    It's essentially the same thing, just written differently. I just tested it on python 2.7.

    root.focus_force() wouldn't work but the above method did.

    0 讨论(0)
  • 2020-12-09 10:56

    It works for me. I am on Macos Mojave, python 3.6.4. Place this code before root.mainloop()

    import os
    os.system("open -a Python")
    

    When you open -a an application that already be opened, this application will be focus on.

    0 讨论(0)
  • 2020-12-09 10:58

    Solution for Windows is a littlebit tricky - you can't just steal the focus from another window, you should move your application to foreground somehow. But first, I suggest you to consume a littlebit of windows theory, so we're able to confirm, that this is what we want to achieve.

    As I mentioned in comment - it's a good opportunity to use the SetForegroundWindow function (check restrictions too!). But consider such stuff as a cheap hack, since user "owns" foreground, and Windows would try to stop you at all cost:

    An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.

    Also, check a remark on this page:

    The system automatically enables calls to SetForegroundWindow if the user presses the ALT key or takes some action that causes the system itself to change the foreground window (for example, clicking a background window).

    Here's goes a simplest solution, since we're able to emulate Alt press:

    import tkinter as tk
    import ctypes
    
    #   store some stuff for win api interaction
    set_to_foreground = ctypes.windll.user32.SetForegroundWindow
    keybd_event = ctypes.windll.user32.keybd_event
    
    alt_key = 0x12
    extended_key = 0x0001
    key_up = 0x0002
    
    
    def steal_focus():
        keybd_event(alt_key, 0, extended_key | 0, 0)
        set_to_foreground(window.winfo_id())
        keybd_event(alt_key, 0, extended_key | key_up, 0)
    
        entry.focus_set()
    
    
    window = tk.Tk()
    
    entry = tk.Entry(window)
    entry.pack()
    
    #   after 2 seconds focus will be stolen
    window.after(2000, steal_focus)
    
    window.mainloop()
    

    Some links and examples:

    • Similar problem
    • Example #1
    • Example #2
    0 讨论(0)
  • 2020-12-09 11:08

    For Linux (Ubuntu 16.04.6 LTS) I tried many suggestions including .grab which broke things. In the end I used:

    if self.top2_is_active is True: # Are we already playing songs?
        self.top2.focus_force()     # Get focus
        self.top2.lift()            # Raise in stacking order
        root.update()
        return                      # Don't want to start playing again
    
    

    It's not really "stealing" focus because I have a button on the main window defined as:

    ''' ▶  Play Button '''
    self.play_text="▶  Play"                # play songs window is opened.
    self.listbox_btn2 = tk.Button(frame3, text=self.play_text, \
                        width=BTN_WID, command=self.play_items)
    self.listbox_btn2.grid(row=0, column=1, padx=2)
    

    After clicking this button the text is changed to:

    self.listbox_btn2 ["text"] = "                                                                    
    0 讨论(0)
  • 2020-12-09 11:11

    Not sure what issue you face. But below is sample code which worked great for me.

    from tkinter import *
    
    window = Tk()
    
    def handle_focus(event):
        if event.widget == window:
            window.focus_set()
            input1.focus_set()
    
    
    label1 = Label(window,text = "Enter Text 2")
    input1 = Entry(window, bd=5)
    
    label2 = Label(window,text = "Enter Text 2")
    input2 = Entry(window, bd=5)
    
    submit = Button(window, text="Submit")
    
    label1.pack()
    input1.pack()
    label2.pack()
    input2.pack()
    submit.pack(side=BOTTOM)
    
    window.lift()
    window.attributes("-topmost", True)
    
    window.bind("<FocusIn>", handle_focus)
    
    hwnd = window.winfo_id()
    
    window.mainloop()
    

    This was tested using Latest Python 3.6 on Windows 10.

    The result was that after running the program, I could just start typing and and he input would go to the first text box

    0 讨论(0)
提交回复
热议问题