How do I create a modal dialog in tkinter?

I have an MFC application that runs some built-in Python scripts. I am trying to make one of the dialogs this inline script creates a modal, but I am not having much success.

Can anyone point me to a way to make a modal dialog? Do I need to use windows functions for this, or is it just Tk or Python functions enough?

For what I have googled, it looks like the following combination of functions should do the magic, but they don't seem to work as I expected:

focus_set()

grab_set()

transient(parent)

      

+2


source to share


2 answers


grab_set

is the correct mechanism for creating the application modality window. That is, it accepts all input from all other windows in the same application (that is: other Tkinter windows in the same process), but allows interaction with other applications.

If you want your dialog to be globally modal use grab_set_global

. This will require entering all keyboards and mice for the entire system. You have to be very careful when using this because you can easily lock yourself out of your computer if you have a bug that prevents your application from releasing the capture.



When I need to do this, during development, I will try to write a skip-protected fault tolerance such as a timer that will release the capture after a certain amount of time.

+4


source


In one of my projects, I used the Tcl window manager attribute '-disabled' on the parent window, which brought up the (modal) toplevel dialog.

Don't know what windows you show by an MFC application are created or used with Tcl stuff, but if your parent window is Tk based, you can do this:

In Python, just call the parent window inside your top window's create method:

MyParentWindow.wm_attributes("-disabled", True)

      

Once you've got what you want in your modal window, remember to use the callback function inside your modal window to re-enable input in the parent window! (otherwise you won't be able to interact with the parent window anymore!):



MyParentWindow.wm_attributes("-disabled", False)

      

A Tkinter (Tcl Version 8.6) Python example (tested on Windows 10 64 bit):

# Python 3+
import tkinter as tk
from tkinter import ttk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.minsize(300, 100)
        self.button = ttk.Button(self, text="Call toplevel!", command=self.Create_Toplevel)
        self.button.pack(side="top")

    def Create_Toplevel(self):

        # THE CLUE
        self.wm_attributes("-disabled", True)

        # Creating the toplevel dialog
        self.toplevel_dialog = tk.Toplevel(self)
        self.toplevel_dialog.minsize(300, 100)

        # Tell the window manager, this is the child widget.
        # Interesting, if you want to let the child window 
        # flash if user clicks onto parent
        self.toplevel_dialog.transient(self)



        # This is watching the window manager close button
        # and uses the same callback function as the other buttons
        # (you can use which ever you want, BUT REMEMBER TO ENABLE
        # THE PARENT WINDOW AGAIN)
        self.toplevel_dialog.protocol("WM_DELETE_WINDOW", self.Close_Toplevel)



        self.toplevel_dialog_label = ttk.Label(self.toplevel_dialog, text='Do you want to enable my parent window again?')
        self.toplevel_dialog_label.pack(side='top')

        self.toplevel_dialog_yes_button = ttk.Button(self.toplevel_dialog, text='Yes', command=self.Close_Toplevel)
        self.toplevel_dialog_yes_button.pack(side='left', fill='x', expand=True)

        self.toplevel_dialog_no_button = ttk.Button(self.toplevel_dialog, text='No')
        self.toplevel_dialog_no_button.pack(side='right', fill='x', expand=True)

    def Close_Toplevel(self):

        # IMPORTANT!
        self.wm_attributes("-disabled", False) # IMPORTANT!

        self.toplevel_dialog.destroy()

        # Possibly not needed, used to focus parent window again
        self.deiconify() 


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

      

For more information on Tcl window manager attributes, see the Tcl documentation: https://wiki.tcl.tk/9457

0


source







All Articles