Search code examples
pythontkintermessagebox

Disable window controls when a messagebox is created in tkinter


Is there any way to disable all windows when a messagebox popup is created in tkinter?

Here's the code:

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

Here when the messagebox pops up, I don't want the user to be able to interact with any other Tk or Toplevel windows until that popup is destroyed.

(I tried using the parent attribute of the messagebox, but it only disables one window.)

Is there any way to achieve this in tkinter?

It would be great if anyone could help me out.


Solution

  • After experimenting for a few days, I finally found the solution.

    The basic idea here is to get all the child widgets of a window, check whether the child is an instance of Tk or Toplevel, and apply the -disabled attribute to them.

    Here's the implementation:

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