如何让Tkinter窗口跳到前面?

时间:2009-12-12 04:52:34

标签: python tkinter focus

如何让Tkinter应用程序跳到前面?目前,窗口出现在我所有其他窗口后面,并没有得到焦点。

我应该调用一些方法吗?

11 个答案:

答案 0 :(得分:62)

当您说“我的其他窗口”时,假设您的意思是您的应用程序窗口,您可以在Toplevel或Tk上使用lift()方法:

root.lift()

如果您希望窗口保持在所有其他窗口之上,请使用:

root.attributes("-topmost", True)

root是你的Toplevel还是Tk。不要忘记-前面的"topmost"

要使其临时,请在以下后禁用最右侧:

def raise_above_all(window):
    window.attributes('-topmost', 1)
    window.attributes('-topmost', 0)

只需传入你想要引发的窗口作为参数,这应该可行。

答案 1 :(得分:31)

如果您在Mac上执行此操作,请使用AppleEvents将重点放在Python上。例如:

import os

os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')

答案 2 :(得分:26)

在mainloop()之前添加以下行:

root.lift()
root.attributes('-topmost',True)
root.after_idle(root.attributes,'-topmost',False)

它对我来说非常合适。当窗口生成时,它会使窗口显示在前面,并且它不会始终保持在前面。

答案 3 :(得分:5)

关于Mac,我注意到可能存在一个问题,即如果有多个python GUI在运行,那么每个进程都会被命名为#34; Python"而AppleScript倾向于将错误的推广到前面。这是我的解决方案。我们的想法是在加载Tkinter之前和之后获取正在运行的进程ID列表。 (请注意,这些是AppleScript进程ID,它们似乎与它们的posix对应物无关。去图。)那么奇怪的人将是你的,你将那个移到最前面。 (我并不认为最后的循环是必要的,但是如果你只是得到ID为procID的每个进程,AppleScript显然会返回一个由name标识的对象,当然这是非唯一的&#34 ; 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''')

答案 4 :(得分:4)

最近,我在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()

答案 5 :(得分:4)

某种程度上结合了各种其他方法,这适用于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()

答案 6 :(得分:3)

在Mac OS X上,PyObjC提供了一种更清晰,更不容易出错的方法,而不是炮轰osascript:

import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps

app = NSRunningApplication.runningApplicationWithProcessIdentifier_(os.getpid())
app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps)

答案 7 :(得分:0)

在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运行脚本时,应用程序窗口将停留在后面。

我的解决方案在遇到的所有情况下都有效。

答案 8 :(得分:0)

此答案是使一个Tkinter窗口弹出到其他Tkinter窗口的上方。

在我的应用中,我有一个大窗口toplevel,它调用了一个较小的窗口top2,该窗口最初显示在toplevel的顶部。

如果用户在toplevel窗口中单击,它将获得焦点并窒息小得多的top2窗口,直到将toplevel窗口从窗口中拖出为止。

解决方案是单击toplevel中的按钮以再次启动top2top2打开功能知道它已经在运行,因此只需将其移至顶部并为其聚焦即可:

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

答案 9 :(得分:-1)

当您在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系统才需要它。

答案 10 :(得分:-1)

如果知道您想将目标窗口升起的窗口,则可以简单地使用tkraise方法,并将aboveThis参数设置为您要绘制的窗口。

from tkinter import Tk, ttk, Toplevel

class App(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.title('Main Window')
        self.state('zoomed')
        self.l1 = ttk.Label(self, text='Hello World!')
        self.l1.pack()

        self.s = Splash()
        self.s.tkraise(aboveThis=self)

class Splash(Toplevel):
    def __init__(self):
        Toplevel.__init__(self)
        self.title('Splash Screen')
        self.lift()


app = App()
app.mainloop()