Tkinter主窗口焦点

时间:2014-03-30 23:04:43

标签: python tkinter focus

我有以下代码

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

此代码的作用是它在所有其他窗口上方显示我的Tkinter窗口,但它仍然只解决了一半的问题。虽然窗口实际上显示在所有其他窗口之上,但窗口没有焦点。有没有办法不仅让窗口成为​​Tkinter的最前面的窗口,还关注它?

6 个答案:

答案 0 :(得分:6)

如果focus_force()无效,您可以尝试:

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

它本质上是相同的,只是用不同的方式写的。我刚刚在python 2.7上测试过它。

root.focus_force()不起作用,但上述方法确实有效。

答案 1 :(得分:4)

Windows的解决方案有点棘手 - 您不能只是从另一个窗口窃取焦点,您应该以某种方式将应用程序移动到前台。 但首先,我建议您使用littlebit of windows theory,因此我们能够确认这是我们想要实现的目标。

正如我在comment中提到的那样 - 这是一个使用SetForegroundWindow函数的好机会(也可以检查限制!)。但是考虑到这样的东西是廉价的黑客,因为用户“拥有”前景,而Windows会试图不惜一切代价阻止你:

  

当用户使用另一个窗口时,应用程序无法强制窗口到达前台。相反,Windows会闪烁窗口的任务栏按钮以通知用户。

另外,请在this页面上查看备注:

  

如果用户按下ALT键或采取一些导致系统自身更改前景窗口的操作(例如,单击背景窗口),系统会自动启用对SetForegroundWindow的调用。

这是最简单的解决方案,因为我们可以模仿Alt按:

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()

一些链接和示例:

答案 2 :(得分:0)

不确定您面临的问题。但下面的示例代码对我来说很有用。

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()

这是在Windows 10上使用Latest Python 3.6测试的。

Test Results

结果是在运行程序后,我可以开始输入,并且输入将转到第一个文本框

答案 3 :(得分:0)

注意:这是Windows特定的。这会聚焦整个主窗口。基本上强制alt-tab到达窗口。

这些答案都不适用于我,tk窗口会显示在-topmost标志的所有内容之上,我的输入框会有焦点,但窗口本身不会,这意味着打字不会出现在tk窗口中。它看起来像这样:

enter image description here

添加对Windows API的调用有助于窃取焦点:

import win32gui    
root = tk.Tk()

# Application specific setup ...

win32gui.SetForegroundWindow(root.winfo_id())

免责声明:窃取焦点是不良行为,因此只有在必要时才使用它,如果有意义,例如用户将立即输入的输入框。

答案 4 :(得分:0)

对我有用。我在Macos Mojave,python 3.6.4上。将此代码放在root.mainloop()

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

当您打开-a已打开的应用程序时,该应用程序将被重点关注。

答案 5 :(得分:0)

对于Linux(Ubuntu 16.04.6 LTS),我尝试了很多建议,包括.grab,这些建议会导致问题。最后,我使用了:

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

这并不是真正的“窃取”焦点,因为我在主窗口上定义了一个按钮:

''' ▶  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)

单击此按钮后,文本更改为:

self.listbox_btn2 ["text"] = "?  Show playing"     # Play button