在 tkinter 中创建消息框时禁用窗口控件

时间:2021-03-10 11:35:08

标签: python tkinter messagebox

在 tkinter 中创建消息框弹出窗口时,有没有办法禁用所有窗口?

代码如下:

from tkinter import *
from tkinter import messagebox

def show():
    messagebox.showinfo("Test Popup", "Hello world")

root = Tk()
root.title("Main Window")
root.geometry("500x500")

toplevel = Toplevel(root)
toplevel.title("Toplevel Window")
toplevel.geometry("300x300")

show_button = Button(root , text = "Show popup" , command = show)
show_button.place(x = 200 , y = 200)

mainloop()

在这里,当消息框弹出时,我不希望用户能够与任何其他 TkToplevel 窗口交互,直到该弹出窗口被销毁。

(我尝试使用 parentmessagebox 属性,但它只能禁用一个窗口。)

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

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

2 个答案:

答案 0 :(得分:0)

我认为不可能阻止与窗口的所有交互,例如移动它们(除非您使用 .overrideredirect(True) 这将使窗口装饰消失并且寡妇将停止由窗口管理器处理).

但是,可以

  1. 防止顶层出现在弹出窗口的顶部

  2. 在显示弹出窗口时禁用根窗口和顶层的“关闭”按钮

对于这两种情况,我在 show() 中使用以下总体思路:

def show():
    # modify state of root and toplevel to make them less interactive
    # ...
    messagebox.showinfo("Test Popup", "Hello world", parent=root)
    # put root and toplevel back in their normal state
    # ...

对于 1. 我在显示弹出窗口之前使用 root.attributes('-topmost', True),它从 root 继承此属性,因此将保留在 toplevel 之上。

对于 2. 我使用 window.protocol("WM_DELETE_WINDOW", lambda: quit(window)),当用户单击窗口的关闭按钮时调用 quit(window)。在 quit() 中,我在销毁窗口之前检查是否打开了弹出窗口:

def quit(window):
    if not popup:
        window.destroy()

popup 是一个全局变量,其值在 show() 中发生变化。

完整代码:

import tkinter as tk
from tkinter import messagebox

def quit(window):
    if not popup:  # destroy the window only if popup is not displayed
        window.destroy()

def show():
    global popup
    popup = True
    root.attributes('-topmost', True)
    messagebox.showinfo("Test Popup", "Hello world", parent=root)
    root.attributes('-topmost', False)
    popup = False

root = tk.Tk()
popup = False
root.protocol("WM_DELETE_WINDOW", lambda: quit(root))
root.title("Main Window")
root.geometry("500x500")

toplevel = tk.Toplevel(root)
toplevel.protocol("WM_DELETE_WINDOW", lambda: quit(toplevel))
toplevel.title("Toplevel Window")

show_button = tk.Button(root, text="Show popup", command=show)
show_button.pack()

root.mainloop()

您可能可以在 show() 中添加更多内容,例如.resizable(False, False) 如果您不希望用户在显示弹出窗口时调整窗口大小。

答案 1 :(得分:0)

尝试了几天,终于找到了解决方案。

这里的基本思想是获取一个窗口的所有子窗口部件,检查子窗口部件是 Tk 还是 Toplevel 的实例,并将 -disabled 属性应用于它们。

这是实现:

from tkinter import *
from tkinter import messagebox

def disable_windows(window):
    for child in window.winfo_children(): # Get all the child widgets of the window
        if isinstance(child, Tk) or isinstance(child, Toplevel): # Check if the child is a Tk or Toplevel window so that we can disable them
            child.attributes('-disabled', True)
            disable_windows(child)

def enable_windows(window):
    for child in window.winfo_children(): # Get all the child widgets of the window
        if isinstance(child , Tk) or isinstance(child , Toplevel): # Check if the child is a Tk or Toplevel window so that we can enable them
            child.attributes('-disabled' , False)
            enable_windows(child)

def increase_popup_count():
    global popup_count
    popup_count += 1
    if popup_count > 0: # Check if a popup is currently active so that we can disable the windows
        disable_windows(root)
    else: # Enable the windows if there is no active popup
        enable_windows(root)

def decrease_popup_count():
    global popup_count
    popup_count -= 1
    if popup_count > 0: # Check if a popup is currently active so that we can disable the windows
        disable_windows(root)
    else: # Enable the windows if there is no active popup
        enable_windows(root)

def showinfo(title, message): # A custom showinfo funtion
    increase_popup_count() # Increase the 'popup_count' when the messagebox shows up
    messagebox.showinfo(title , message)
    decrease_popup_count() # Decrease the 'popup_count' after the messagebox is destroyed

def show():
    showinfo("Test Popup", "Hello world")

root = Tk()
root.title("Main Window")
root.geometry("500x500")

popup_count = 0

toplevel = Toplevel(root)
toplevel.title("Toplevel Window")
toplevel.geometry("400x400")

toplevel_2 = Toplevel(toplevel)
toplevel_2.title("Toplevel Window of Another Toplevel")
toplevel_2.geometry("300x300")

show_button = Button(root , text = "Show popup" , command = show)
show_button.place(x = 200 , y = 200)

mainloop()
相关问题