Question

I have code for selecting backup that should be loaded. It opens Toplevel window and lets you select one of the backups to load. When this window opens, I would like to block input to original window, so the only way to get back to original window is by closing the new Toplevel window.

The part of code that I hoped would work:

from tkinter import *



class BackupsGui:
    def __init__(self, parent):
        top = Toplevel()
        self.top = top

Some more code and __init__ ending with:

        top.update_idletasks()
        top.overrideredirect(True)
        top.mainloop()

or:

        top.transient(parent)
        top.mainloop()

Niether code part appears to change Toplevel interaction in any way, nor does changing if top.mainloop() precedes top.transient() or top.update_idletasks().

What do I miss?

Was it helpful?

Solution

transient and overrideredirect have nothing to do with event handling. If you want to block all input except for the toplevel, you need to call grab_set on the toplevel window. This will cause all events to be sent to that window.

Run the following code, and notice that if you don't check the box, you can continue to create new windows and change the value of the checkbox. Once checked, the next window grabs all events, preventing you from interacting with the other windows.

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)
        self.do_grab = tk.BooleanVar()
        cb = tk.Checkbutton(self, text="New window grabs all events", 
                            variable=self.do_grab, onvalue=True, offvalue=False)
        cb.pack()
        new_button = tk.Button(self, text="New window", command=self.on_click)
        new_button.pack()

    def on_click(self):
        self.top = tk.Toplevel(self)
        button = tk.Button(self.top, text="dismiss", command=self.top.destroy)
        do_grab = self.do_grab.get()

        if do_grab:
            label = tk.Label(self.top, wraplength=200,
                             text="This window grabs all events")
        else:
            label = tk.Label(self.top, wraplength = 200, 
                             text="This window does NOT grab all events")
        label.pack(fill="x")
        button.pack()

        if do_grab:
            self.top.grab_set()

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top