如何让 Tkinter 窗口跳转到最前面?
- 2025-01-14 08:50:00
- admin 原创
- 112
问题描述:
如何让 Tkinter 应用程序跳转到最前面?目前,该窗口出现在我所有其他窗口的后面,并且没有获得焦点。
我应该调用一些方法吗?
解决方案 1:
假设您在说“我的其他窗口”时指的是您的应用程序窗口,您可以lift()
在 Toplevel 或 Tk 上使用该方法:
root.lift()
如果您希望窗口位于所有其他窗口之上,请使用:
root.attributes("-topmost", True)
你的 Toplevel 或 Tk 在哪里root
。别忘了-
前面的"topmost"
!
为了使其成为临时的,请在之后禁用最顶层:
def raise_above_all(window):
window.attributes('-topmost', 1)
window.attributes('-topmost', 0)
只需将您想要提升的窗口作为参数传入,就可以了。
解决方案 2:
在 mainloop() 之前添加以下几行:
root.lift()
root.attributes('-topmost',True)
root.after_idle(root.attributes,'-topmost',False)
它对我来说非常完美。它使窗口在生成时移到最前面,并且不会一直保持在最前面。
解决方案 3:
如果您在 Mac 上执行此操作,请使用 AppleEvents 将焦点放在 Python 上。例如:
import os
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
解决方案 4:
关于 Mac,我注意到如果运行多个 Python GUI,则可能会出现一个问题,即每个进程都将被命名为“Python”,而 AppleScript 往往会将错误的进程提升到最前面。这是我的解决方案。这个想法是在加载 Tkinter 之前和之后获取正在运行的进程 ID 列表。(请注意,这些是 AppleScript 进程 ID,似乎与它们的 posix 对应项没有任何关系。去想一想。)然后,奇怪的人将属于你,你将那个人移到最前面。(我不认为最后的循环是必要的,但如果你只是获取 ID 为 procID 的每个进程,AppleScript 显然会返回一个由名称标识的对象,当然是那个非唯一的“Python”,所以除非我遗漏了什么,否则我们又回到了原点。)
import Tkinter, subprocess
def applescript(script):
return subprocess.check_output(['/usr/bin/osascript', '-e', script])
def procidset():
return set(applescript(
'tell app "System Events" to return id of every process whose name is "Python"'
).replace(',','').split())
idset = procidset()
root = Tkinter.Tk()
procid = iter(procidset() - idset).next()
applescript('''
tell app "System Events"
repeat with proc in every process whose name is "Python"
if id of proc is ''' + procid + ''' then
set frontmost of proc to true
exit repeat
end if
end repeat
end tell''')
解决方案 5:
在 Mac OS X 上,PyObjC 提供了一种比 osascript 更干净、更不容易出错的方法:
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
解决方案 6:
最近,我在 Mac 上遇到了同样的问题。我结合了针对@MagerValp
Mac 和@D K
其他系统的几个答案:
import platform
if platform.system() != 'Darwin':
root.lift()
root.call('wm', 'attributes', '.', '-topmost', True)
root.after_idle(root.call, 'wm', 'attributes', '.', '-topmost', False)
else:
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
root.mainloop()
解决方案 7:
在某种程度上,它是各种其他方法的组合,适用于 OS X 10.11 和在 venv 中运行的 Python 3.5.1,也适用于其他平台。它还通过进程 ID 而不是应用程序名称来定位应用程序。
from tkinter import Tk
import os
import subprocess
import platform
def raise_app(root: Tk):
root.attributes("-topmost", True)
if platform.system() == 'Darwin':
tmpl = 'tell application "System Events" to set frontmost of every process whose unix id is {} to true'
script = tmpl.format(os.getpid())
output = subprocess.check_call(['/usr/bin/osascript', '-e', script])
root.after(0, lambda: root.attributes("-topmost", False))
您可以在调用之前立即调用它mainloop()
,如下所示:
raise_app(root)
root.mainloop()
解决方案 8:
当您在 Tkinter._test() 函数中调用 mainloop() 时,有一个关于如何使 Tkinter 窗口获得焦点的提示。
# The following three commands are needed so the window pops
# up on top on Windows...
root.iconify()
root.update()
root.deiconify()
root.mainloop()
这是我发现的最干净、最正确的方法,但它仅适用于 Windows 系统。
解决方案 9:
这个答案是让一个 Tkinter 窗口弹出到其他 Tkinter 窗口之上。
在我的应用程序中,我有一个大窗口,它调用一个最初出现在其顶部的toplevel
小得多的窗口。top2
`toplevel`
如果用户在toplevel
窗口内单击,它将获得焦点并抑制更小的top2
窗口,直到toplevel
窗口被拖出。
解决方案是单击按钮再次toplevel
启动top2
。top2
open 函数知道它已经在运行,因此只需将其提升到顶部并赋予其焦点:
def play_items(self):
''' Play 1 or more songs in listbox.selection(). Define buttons:
Close, Pause, Prev, Next, Commercial and Intermission
'''
if self.top2_is_active is True:
self.top2.focus_force() # Get focus
self.top2.lift() # Raise in stacking order
root.update()
return # Don't want to start playing again
解决方案 10:
在 macOS High Sierra,py3.6.4 上,这是我的解决方案:
def OnFocusIn(event):
if type(event.widget).__name__ == 'Tk':
event.widget.attributes('-topmost', False)
# Create and configure your root ...
root.attributes('-topmost', True)
root.focus_force()
root.bind('<FocusIn>', OnFocusIn)
这个想法是将它带到前面直到用户与它交互,即获得焦点。
我尝试了可接受的答案, .after_idle()
和.after()
。它们都在一种情况下失败:当我直接从 PyCharm 等 IDE 运行脚本时,应用程序窗口将停留在后面。
我的解决方案在我遇到的所有情况下都有效。
解决方案 11:
这会将窗户抬到前面,并且焦点也会集中在窗户上。
def lift_window(window):
window.attributes('-topmost',True)
window.attributes('-topmost',False) # disable the topmost attribute after it is at the front to prevent permanent focus
window.focus_force() # focus to the window
解决方案 12:
还有一行(Python 3.11 和 tkinter 8.6 需要):
def lift_window(window):
window.attributes('-topmost', True)
window.update_idletasks() # get window on top
window.attributes('-topmost', False) # prevent permanent focus
window.focus_force() # focus to the window