繁体   English   中英

Tkinter 主窗口焦点

[英]Tkinter main window focus

我有以下代码

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

这段代码的作用是将我的 Tkinter 窗口显示在所有其他窗口之上,但它仍然只解决了一半的问题。 虽然该窗口实际上显示在所有其他窗口之上,但该窗口没有焦点。 有没有办法不仅使窗口成为 Tkinter 中最前面的窗口,而且还可以将焦点放在它上面?

如果focus_force()不起作用,您可以尝试执行以下操作:

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

本质上是一样的,只是写法不同。 我刚刚在 python 2.7 上测试了它。

root.focus_force()不起作用,但上述方法起作用了。

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

正如我在评论中提到的 - 这是使用SetForegroundWindow函数的好机会(也请检查限制!)。 但是将此类东西视为廉价黑客,因为用户“拥有”前景,而 Windows 会不惜一切代价阻止您:

当用户正在使用另一个窗口时,应用程序不能将窗口强制为前台。 相反,Windows 会闪烁窗口的任务栏按钮以通知用户。

另外,请检查页面上的评论:

如果用户按下 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()

一些链接和示例:

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

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 上使用最新的 Python 3.6 测试的。

检测结果

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

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


这些答案都不适合我, tk窗口将出现在所有带有-topmost标志的顶部,我的输入框将具有焦点,但窗口本身不会,这意味着输入不会出现在tk窗口中. 它看起来像这样:

在此处输入图片说明

添加对 Windows API 的调用以窃取焦点是有帮助的:

import win32gui    
root = tk.Tk()

# Application specific setup ...

win32gui.SetForegroundWindow(root.winfo_id())

免责声明:窃取焦点是不好的行为,所以只有在你必须并且有意义的情况下才使用它,例如用户会立即输入的输入框。

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

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

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

对于 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM