Is it necessary to call Tk() when writing a GUI app with Tkinter?

Rick Johnson rantingrickjohnson at gmail.com
Wed Feb 29 09:24:40 EST 2012


On Feb 28, 11:06 pm, John Salerno <johnj... at gmail.com> wrote:
> The book I'm reading about using Tkinter only does this when creating the top-level window:
>
> app = Application()
> app.mainloop()
>
> and of course the Application class has subclassed the tkinter.Frame class.
>
> However, in the Python documentation, I see this:
>
> root = Tk()
> app = Application(master=root)
> app.mainloop()
> root.destroy()
>
> Is it necessary to explicitly call Tk(), then pass that result as an argument for the Application call? Is it also necessary to call destroy() on the root frame?

It is not necessarily to call Tk explicitly, which i think is a bug
BTW. Sure, for simple scripts you can save one line of code but only
at the expense of explicitness and intuitiveness. Observe

## START CODE ##
import Tkinter as tk

root = tk.Tk()
root.title('Explicit Root')
root.mainloop()

f = tk.Frame(master=None, width=100, height=100, bg='red')
f.pack()
f.mainloop()

b = tk.Button(master=None, text='Sloppy Coder')
b.pack()
b.mainloop()
## END CODE ##

as you can see all three examples work even though the last two don't
explicitly create a master. The master is still there however Tkinter
just created "magically" for you. Talk about laziness!

> I tried the above and I got the following error:
>
> Traceback (most recent call last):
>   File "C:\Users\John\Desktop\gui.py", line 12, in <module>
>     root.destroy()
>   File "C:\Python32\lib\tkinter\__init__.py", line 1714, in destroy
>     self.tk.call('destroy', self._w)
> _tkinter.TclError: can't invoke "destroy" command:  application has been destroyed
>
> So apparently closing the window with the X button (on Windows) implicitly calls the destroy() method of the root frame. If that's the case, why does the documentation explicitly call it?

Because the documentation is FLAWED! Please provide links to this
"documentation" so we can post it on the Wall Of Shame.

> Furthermore, I pasted the exact example from the documentation into IDLE and ran it, and I also go the same error, so the example in the documentation doesn't even work.

IDLE uses the same Python as the command line so naturally it will
throw the same error. ;-)

> So is it sufficient simply to create an Application instance, use mainloop, and then handle the closing of the window elsewhere in the program (such as a widget calling the destroy method on-click, or just letting the X button do it)?

Most applications will have both: user destroying, and program
destroying. Again, your example is FLAWED. Here is a simplified
example:

## START CODE ##

from tkMessageBox import askyesnocancel

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title('Close Me -->')
        self.protocol("WM_DELETE_WINDOW", self.onDestroyWindow)

    def onDestroyWindow(self):
        title = 'Confirm App Exit'
        msg = 'Save changes before exiting?'
        result = askyesnocancel(title, msg, default='cancel')
        if result is None:
            return
        elif result is True:
            print 'saving changes'
        elif result is False:
            print 'dont save changes'
        self.destroy()

if __name__ == '__main__':
    app = App()
    app.mainloop()

## END CODE ##



More information about the Python-list mailing list