【问题标题】:How to put a toplevel window in front of the main window in tkinter?如何在 tkinter 的主窗口前面放置一个顶层窗口?
【发布时间】:2021-02-21 08:00:30
【问题描述】:

有没有办法在主窗口前面放一个顶层窗口?

代码如下:

from tkinter import *

root = Tk()
root.geometry('1280x720')

def create_new_window():
    root2 = Toplevel()
    root2.geometry('500x500')

create_new_window()

mainloop()

在这里,我希望root2 窗口始终保持在root 窗口前面。

我尝试使用root2.attributes('-topmost' , 1),但问题是这一行也将窗口置于所有其他程序之上。

我想要的是顶层窗口应该只在主窗口的前面,当我点击主窗口时它不应该返回。

有没有办法在 tkinter 中实现这一点?

如果有人能帮助我,那就太好了。

【问题讨论】:

  • 你试过root.update_idletasks()吗?
  • @Atlas435:这会将顶层窗口带到主窗口的前面,但它只会这样做一次。所以如果我点击主窗口,顶层窗口会再次返回。
  • @CoolCloud:我用root2.focus_force()看不出有什么不同。
  • 我把问题读错了,我以为你只是想把窗户带到前面,而不是永远呆在那里。

标签: python tkinter toplevel topmost


【解决方案1】:

我认为你想要的是一个短暂的窗口,你需要这样做:

root2.wm_transient(root)

来自手册:

wm 瞬态窗口 ?master? 如果指定了 master,则通知窗口管理器 window 是一个临时窗口(例如下拉菜单),代表 master 工作(其中 master 是*窗口的路径名)。如果 master 被指定为空字符串,则 window 被标记为不再是临时窗口。否则,该命令返回窗口当前主窗口的路径名,如果窗口当前不是临时窗口,则返回空字符串。瞬态窗口将镜像 master 中的状态更改,并在最初映射时继承 master 的状态。试图使窗口成为自身的瞬态是错误的。

【讨论】:

    【解决方案2】:

    所以你可以做这样的事情,但对我来说似乎有问题。 我所做的是将 FocusOut 事件绑定到创建的顶层,所以每次它失去焦点时都会触发事件 stackingorder 将windos放在右边命令。您可能需要为您选择的几个事件使此代码过期,但为了让您了解.. 代码如下:

    import tkinter as tk
    
    def add_toplevel(idx, toplevel):
        if idx == 'end':
            idx = len(toplevels)
        toplevels.insert(idx,toplevel)
    
    def create_new_window():
        root2 = tk.Toplevel()
        root2.geometry('500x500')
        add_toplevel('end',root2)
        root2.bind('<FocusOut>', stackingorder)
    
    def stackingorder(event):
        for toplevel in toplevels:
            toplevel.lift()
            toplevel.update_idletasks()
    
    toplevels = [] #stacking order by index
    
    root = tk.Tk()
    
    create_new_window()
    
    
    root.mainloop()
    

    您可能也对此感兴趣: https://*.com/a/10391659/13629335

    【讨论】:

    • 感谢您的回答@Atlas345。您的回答对我帮助很大,但另一个答案中的方法对我来说更容易,所以我接受了那个。请不要误会我的意思。你的回答很有帮助。点赞!
    • @Lenovo360 同意,到目前为止更好的答案。