【问题标题】:Tkinter messagebox fails when the root window is closed关闭根窗口时,Tkinter 消息框失败
【发布时间】:2021-03-16 17:25:00
【问题描述】:

当我关闭父窗口忽略消息框时,Tkinter 消息框生成异常。

import tkinter as tk
from tkinter import messagebox 
root = tk.Tk()
root.geometry("100x100")
w = tk.Label(root, text="I am root")
w.pack()
messagebox.showerror("Message Box", "Error")
root.mainloop()

这很痛苦,因为我想在根窗口关闭后进行处理。我看不到任何使消息框窗口模式化的方法。我可以设置自己的对话框,但如果可以的话,我宁愿使用标准的现成代码。

【问题讨论】:

  • 如何复制该异常?我可以正确关闭窗口或消息框。
  • 在Thonny中打开上面的代码。点击运行按钮。忽略前面的消息框。点击它后面灰色窗口的关闭按钮。错误是:_tkinter.TclError:无法调用“grab”命令:应用程序已被破坏。我在终端和空闲时得到相同的结果。我希望这是一个已知的错误。最好还是一个固定的已知错误。谷歌似乎没有帮助。我正在使用 Python 3.8.5 和 Xubuntu 20.04。

标签: python tkinter


【解决方案1】:

我建议的解决方案是在关闭消息框之前捕获主关闭时生成的消息框异常。这适用于消息框,但不适用于简单的对话框。最好的解决方案似乎是在打开对话框之前禁用主窗口上的关闭按钮,然后重新启用它。下面是一个简单的例子来说明这个过程:

import tkinter as tk
from tkinter import simpledialog
close_enabled = False # Main window close button enabled.

def On_Closing():
    # User has clicked the main window close button.
    if close_enabled == False: return
    print('Close down processing')
    root.destroy()

root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", On_Closing)
root.geometry("100x100")
w = tk.Label(root, text="I am root")
w.pack()
close_enabled = False # Disable main window close button.
answer = simpledialog.askstring('Title', 'Type Your Name')
close_enabled = True # Enable main window close button.
print(answer)
root.mainloop()

唯一的缺点是当单击(停用的)主窗口关闭按钮时,对话框会在主窗口后面消失。消息框确实位于顶部,这对我更有帮助。

【讨论】:

    【解决方案2】:

    对于您的情况,您需要在显示消息框之前致电root.wait_visibility()

    import tkinter as tk
    from tkinter import messagebox 
    root = tk.Tk()
    root.geometry("100x100")
    w = tk.Label(root, text="I am root")
    w.pack()
    root.wait_visibility()
    messagebox.showerror("Message Box", "Error")
    root.mainloop()
    

    【讨论】:

    • 不,这不适用于 Python 3.8.5 和 Xubuntu 20.04。我仍然得到:_tkinter.TclError:无法调用“grab”命令:应用程序已被销毁
    • 然后尝试在显示消息框之前调用root.withdraw(),之后再调用root.deiconify()
    • 可行,但用户看到主窗口消失并没有吸引力。如果我自己编写对话框,我可以使用 root.wait_window(child),但如果我使用消息框,我没有子句柄。正如我所说,我可以使用 try: ..... 除了:shut_down()。尽管如此,JeffUK 说消息框在他的机器上工作正常。我更喜欢那个解决方案。
    【解决方案3】:

    默认情况下,消息框附加到第一个运行的窗口,您可以覆盖它并指定另一个窗口,因此作为一种解决方法,您可以将消息框的“主”设置为隐藏窗口,用户无法关闭。即:

    import tkinter as tk
    from tkinter import messagebox 
    root = tk.Tk()
    root.geometry("100x100")
    w = tk.Label(root, text="I am root 1")
    w.pack()
    
    root2 = tk.Tk()
    root2.withdraw()
    
    messagebox.showerror("Message Box", "Error", master=root2)
    
    root.mainloop()
    

    【讨论】:

    • 是的,这是一个很好的尝试。它适用于简单的示例。它遇到了 messagebox.askyesno 的问题。当消息框可见时,我们无用的用户关闭了 root。然后他关闭返回 False 值的消息框。我遇到了处理问题,因为主窗口已经消失。我可以捕获主窗口关闭事件并设置一个标志,但这很麻烦。更简单地说,我不能打扰 root2 并且只是捕获异常。然后我可以调用关闭代码和 sys.exit。同样,如果我必须对每个消息框都这样做,那就太麻烦了。
    猜你喜欢
    • 2019-06-30
    • 2012-11-05
    • 2023-02-24
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 2023-02-26
    • 2021-07-02
    • 1970-01-01
    相关资源
    最近更新 更多