Python: Tkinter: Why is it root.mainloop() and not app.mainloop()
Question: I'm a new member to Stack Overflow. I found this thread, but was not allowed
to comment or ask questions on it, so I thought I'd just reference it here:
[How can I make a in interactive list in Python's Tkinter complete with
buttons that can edit those
listings?](http://stackoverflow.com/questions/18201195/how-can-i-make-a-in-
interactive-list-in-pythons-tkinter-complete-with-buttons-t)

    
    
    from tkinter import *
    import os
    import easygui as eg
    
    class App:
    
        def __init__(self, master):
            frame = Frame(master)
            frame.pack()
    
            # character box
            Label(frame, text = "Characters Editor").grid(row = 0, column = 0, rowspan = 1, columnspan = 2)
            charbox = Listbox(frame)
            for chars in []:
                charbox.insert(END, chars)
            charbox.grid(row = 1, column = 0, rowspan = 5)
            charadd = Button(frame, text = "   Add   ", command = self.addchar).grid(row = 1, column = 1)
            charremove = Button(frame, text = "Remove", command = self.removechar).grid(row = 2, column = 1)
            charedit = Button(frame, text = "    Edit    ", command = self.editchar).grid(row = 3, column = 1)
    
        def addchar(self):
            print("not implemented yet")
        def removechar(self):
            print("not implemented yet")
        def editchar(self):
            print("not implemented yet")
    
    
    root = Tk()
    root.wm_title("IA Development Kit")
    app = App(root)
    root.mainloop()
    

Could somebody explain to me why the very last line is root.mainloop()? Being
a novice with Python, and coming from a background that's procedural-oriented
with no object-orient experience, I would have thought it would have been
app.mainloop().

In fact app = App(root) , app is never used again in the rest of the code! I'm
having trouble understanding why root.mainloop() still works.


Answer: I'm not sure if you'll find this answer satisfying, but you call
`root.mainloop()` because `root` is the object that has the `mainloop` method.
In the code you've given, `App` has no `mainloop` function.

In simpler terms, this is just how tkinter works -- you always end your script
by calling the `mainloop` method of the root window. When that method returns,
your program will exit.

Let's start at the beginning. The simplest, non-OO Tkinter program is going to
look like the following example. Note that this is a python 2.x example, and I
do not use a global import since I think global imports are bad.

    
    
    import Tkinter as tk
    root = tk.Tk()
    <your widgets go here>
    root.mainloop()
    

Many people find that a pure procedural style is not an effective way to write
code, so they might choose to write this in an object-oriented style. It's
natural to think of "the app" as a singleton object. There are many ways to do
this -- the one in your question is, unfortunately, not one of the clearer
ways to do it.

A slightly better way, IMO, would be to structure the code like this:

    
    
    class App(tk.Tk):
        def __init__(self, *args, **kwargs):
            tk.Tk.__init__(self, *args, **kwargs)
            <your widgets go here>
    app = App()
    app.mainloop()
    

In this case, `mainloop` is still being called, though now it's a method of
`App` since `App` inherits from `Tk`. It is conceptually the same as
`root.mainloop()` since in this case, `app` _is_ the root window even though
it goes by a different name.

So, in both cases, `mainloop` is a method that belongs to the root window. And
in both cases, it must be called for the GUI to function properly.

There is a third variation which is what the code you picked is using. And
with this variation, there are several ways to implement it. The variation is
your question uses a class to define the GUI, but does _not_ inherit from
`Tk`. This is perfectly fine, but you still must call `mainloop` at some
point. Since you don't create (or inherit) a `mainloop` function in your
class, you must call the one associated with the root window. The variations I
speak of are how and where the instance of `App` is added to the root window,
and how `mainloop` is ultimately called.

Personally I prefer that `App` inherits from `Frame`, and that you pack the
app _outside_ the definition of the app. The template I use looks like this:

    
    
    class App(tk.Frame):
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
            <your widgets go here>
    
    if __name__ == "__main__":
        root = tk.Tk()
        app = App(root)
        app.pack(fill="both", expand=True)
        root.mainloop()
    

In this final example, `app` and `root` are two completely different objects.
`app` represents a frame that exists _inside_ the root window. Frames are
commonly used this way, as a container for groups of other widgets.

So, in all cases, `mainloop` must be called. _where_ it is called, and how,
depends a bit on your coding style. Some people prefer to inherit from the
root window, some don't. In either case, you must call the `mainloop` function
of the root window.

