如何让 Tkinter 应用程序跳转到前面?目前,该窗口出现在我所有其他窗口的后面并且没有获得焦点。
有什么我应该调用的方法吗?
假设您说“我的其他窗口”时指的是您的应用程序窗口,您可以lift()
在 Toplevel 或 Tk 上使用该方法:
root.lift()
如果您希望窗口保持在所有其他窗口之上,请使用:
root.attributes("-topmost", True)
root
您的 Toplevel 或 Tk在哪里。别忘了-
前面"topmost"
!
要使其成为临时的,请在以下之后立即禁用 topmost:
def raise_above_all(window):
window.attributes('-topmost', 1)
window.attributes('-topmost', 0)
只需传入您要作为参数提出的窗口,这应该可以。
在 mainloop() 之前添加以下行:
root.lift()
root.attributes('-topmost',True)
root.after_idle(root.attributes,'-topmost',False)
它非常适合我。它使窗口在生成窗口时出现在最前面,并且不会一直保持在最前面。
如果您在 Mac 上执行此操作,请使用 AppleEvents 将重点放在 Python 上。例如:
import os
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
关于 Mac,我注意到可能存在一个问题,即如果有多个 python GUI 正在运行,每个进程都会被命名为“Python”,AppleScript 会倾向于将错误的进程推到前面。这是我的解决方案。这个想法是在加载 Tkinter 之前和之后获取正在运行的进程 ID 列表。(请注意,这些是 AppleScript 进程 ID,它们似乎与 posix 对应的进程 ID 无关。去算一下。)然后奇怪的人将是你的,你把那个人移到最前面。(我不认为最后的循环是必要的,但如果你只是简单地获取 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''')
在 Mac OS X 上,PyObjC 提供了一种比使用 osascript 更干净且不易出错的方法:
import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps
app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)
最近,我在 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()
在某种程度上是各种其他方法的组合,这适用于 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()
当您在 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 系统。
这个答案是让一个 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
在 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 运行我的脚本时,应用程序窗口将留在后面。
我的解决方案适用于我遇到的所有情况。