简体   繁体   English

如何让 Tkinter 窗口跳到前面?

[英]How to make a Tkinter window jump to the front?

How do I get a Tkinter application to jump to the front?如何让 Tkinter 应用程序跳转到前面? Currently, the window appears behind all my other windows and doesn't get focus.目前,该窗口出现在我所有其他窗口的后面并且没有获得焦点。

Is there some method I should be calling?有什么方法我应该调用吗?

Assuming you mean your application windows when you say "my other windows", you can use the lift() method on a Toplevel or Tk:假设您说“我的其他窗口”时指的是您的应用程序窗口,则可以在 Toplevel 或 Tk 上使用lift()方法:

root.lift()

If you want the window to stay above all other windows, use:如果您希望窗口保持在所有其他窗口之上,请使用:

root.attributes("-topmost", True)

Where root is your Toplevel or Tk.其中root是您的 Toplevel 或 Tk。 Don't forget the - infront of "topmost" !不要忘记-"topmost" topmost "topmost"

To make it temporary , disable topmost right after:要使其成为临时的,请在以下之后立即禁用最上面:

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

Just pass in the window you want to raise as a argument, and this should work.只需传入您想要作为参数提出的窗口,这应该有效。

Add the following lines before the mainloop():在 mainloop() 之前添加以下几行:

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

It works perfectly for me.它非常适合我。 It makes the window come to the front when the window is generated, and it won't keep it always be in the front.它使窗口在生成窗口时出现在最前面,并且不会一直保持在前面。

If you're doing this on a Mac, use AppleEvents to give focus to Python.如果您在 Mac 上执行此操作,请使用 AppleEvents 将焦点放在 Python 上。 Eg:例如:

import os

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

Regarding the Mac, I noticed there can be a problem in that if there are multiple python GUIs running, every process will be named "Python" and AppleScript will tend to promote the wrong one to the front.关于 Mac,我注意到可能存在一个问题,如果有多个 Python GUI 正在运行,每个进程都会被命名为“Python”,而 AppleScript 会倾向于将错误的一个提升到前面。 Here's my solution.这是我的解决方案。 The idea is to grab a list of running process IDs before and after you load Tkinter.这个想法是在加载 Tkinter 之前和之后获取正在运行的进程 ID 列表。 (Note that these are AppleScript process IDs which seem to bear no relation to their posix counterparts. Go figure.) Then the odd man out will be yours and you move that one to frontmost. (请注意,这些是 AppleScript 进程 ID,它们似乎与它们的 posix 对应项无关。去算一下。)然后奇怪的人将是你的,你将那个人移到最前面。 (I didn't think that loop at the end would be necessary, but if you simply get every process whose ID is procID, AppleScript apparently returns the one object identified by name, which of course is that non-unique "Python", so we are back to square one unless there's something I'm missing.) (我不认为最后的循环是必要的,但是如果您只是获取 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''')

On Mac OS X PyObjC provides a cleaner and less error prone method than shelling out to osascript:在 Mac OS X 上,PyObjC 提供了一种比使用 osascript 更简洁、更不容易出错的方法:

import os
from Cocoa import NSRunningApplication, NSApplicationActivateIgnoringOtherApps

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

Recently, I had the same question on the Mac.最近,我在 Mac 上遇到了同样的问题。 I have combined several answers using @MagerValp for the Mac and @DK for other systems:我使用@MagerValp for Mac 和@DK for其他系统组合了几个答案:

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

Somewhat of a combination of various other methods, this works on OS X 10.11, and Python 3.5.1 running in a venv, and should work on other platforms too.某种程度上是各种其他方法的组合,这适用于 OS X 10.11 和在 venv 中运行的 Python 3.5.1,也应该适用于其他平台。 It also targets the app by process id rather than app name.它还通过进程 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))

You call it right before the mainloop() call, like so:您在mainloop()调用之前调用它,如下所示:

raise_app(root)
root.mainloop()

There's a hint on how to make the Tkinter window take focus when you call mainloop() in the Tkinter._test() function.当您在 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()

This is the cleanest most proper way I've found to do this, but it's only needed for Windows systems.这是我发现的最干净、最合适的方法,但只有 Windows 系统需要它。

This answer is to make one Tkinter Window pop up overtop of other Tkinter windows.这个答案是让一个 Tkinter 窗口在其他 Tkinter 窗口的上方弹出。

In my app I have a large window toplevel which calls a much smaller window top2 which initially appears on top of toplevel .在我的应用程序中,我有一个大窗口toplevel ,它调用一个小得多的窗口top2 ,它最初出现在toplevel顶部。

If user clicks within toplevel window it gains focus and smothers much smaller top2 window until toplevel window is dragged off of it.如果用户在toplevel窗口内单击,它会获得焦点并阻塞更小的top2窗口,直到toplevel窗口被拖离它为止。

The solution is to click the button in toplevel to launch top2 again.解决方法是点击toplevel的按钮再次启动top2 The top2 open function knows it is already running so simply lifts it to the top and gives it focus: 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

On macOS High Sierra, py3.6.4, here is my solution:在 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)

The idea is to bring it to the front until user interacts with it, ie, taking focus.这个想法是把它放在前面,直到用户与它交互,即集中注意力。

I tried the accepted answer, .after_idle() , and .after() .我尝试了公认的答案.after_idle().after_idle() .after() They all fail in one case: When I run my script directly from an IDE like PyCharm, the app window will stay behind.它们都在一种情况下失败:当我直接从 PyCharm 等 IDE 运行我的脚本时,应用程序窗口将留在后面。

My solution works in all the cases that I encountered.我的解决方案适用于我遇到的所有情况。

If the window you would like to raise your target window over, is known, you could simpy use the tkraise method with the aboveThis parameter set to the window you wish to draw over. 如果您希望将目标窗口抬起的窗口已知,您可以简单地使用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()

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

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