Best way to structure a tkinter application? Best way to structure a tkinter application? tkinter tkinter

Best way to structure a tkinter application?


I advocate an object oriented approach. This is the template that I start out with:

# Use Tkinter for python 2, tkinter for python 3import tkinter as tkclass MainApplication(tk.Frame):    def __init__(self, parent, *args, **kwargs):        tk.Frame.__init__(self, parent, *args, **kwargs)        self.parent = parent        <create the rest of your GUI here>if __name__ == "__main__":    root = tk.Tk()    MainApplication(root).pack(side="top", fill="both", expand=True)    root.mainloop()

The important things to notice are:

  • I don't use a wildcard import. I import the package as "tk", which requires that I prefix all commands with tk.. This prevents global namespace pollution, plus it makes the code completely obvious when you are using Tkinter classes, ttk classes, or some of your own.

  • The main application is a class. This gives you a private namespace for all of your callbacks and private functions, and just generally makes it easier to organize your code. In a procedural style you have to code top-down, defining functions before using them, etc. With this method you don't since you don't actually create the main window until the very last step. I prefer inheriting from tk.Frame just because I typically start by creating a frame, but it is by no means necessary.

If your app has additional toplevel windows, I recommend making each of those a separate class, inheriting from tk.Toplevel. This gives you all of the same advantages mentioned above -- the windows are atomic, they have their own namespace, and the code is well organized. Plus, it makes it easy to put each into its own module once the code starts to get large.

Finally, you might want to consider using classes for every major portion of your interface. For example, if you're creating an app with a toolbar, a navigation pane, a statusbar, and a main area, you could make each one of those classes. This makes your main code quite small and easy to understand:

class Navbar(tk.Frame): ...class Toolbar(tk.Frame): ...class Statusbar(tk.Frame): ...class Main(tk.Frame): ...class MainApplication(tk.Frame):    def __init__(self, parent, *args, **kwargs):        tk.Frame.__init__(self, parent, *args, **kwargs)        self.statusbar = Statusbar(self, ...)        self.toolbar = Toolbar(self, ...)        self.navbar = Navbar(self, ...)        self.main = Main(self, ...)        self.statusbar.pack(side="bottom", fill="x")        self.toolbar.pack(side="top", fill="x")        self.navbar.pack(side="left", fill="y")        self.main.pack(side="right", fill="both", expand=True)

Since all of those instances share a common parent, the parent effectively becomes the "controller" part of a model-view-controller architecture. So, for example, the main window could place something on the statusbar by calling self.parent.statusbar.set("Hello, world"). This allows you to define a simple interface between the components, helping to keep coupling to a minimun.


Putting each of your top-level windows into it's own separate class gives you code re-use and better code organization. Any buttons and relevant methods that are present in the window should be defined inside this class. Here's an example (taken from here):

import tkinter as tkclass Demo1:    def __init__(self, master):        self.master = master        self.frame = tk.Frame(self.master)        self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)        self.button1.pack()        self.frame.pack()    def new_window(self):        self.newWindow = tk.Toplevel(self.master)        self.app = Demo2(self.newWindow)class Demo2:    def __init__(self, master):        self.master = master        self.frame = tk.Frame(self.master)        self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)        self.quitButton.pack()        self.frame.pack()    def close_windows(self):        self.master.destroy()def main():     root = tk.Tk()    app = Demo1(root)    root.mainloop()if __name__ == '__main__':    main()

Also see:

Hope that helps.


This isn't a bad structure; it will work just fine. However, you do have to have functions in a function to do commands when someone clicks on a button or something

So what you could do is write classes for these then have methods in the class that handle commands for the button clicks and such.

Here's an example:

import tkinter as tkclass Window1:    def __init__(self, master):        pass        # Create labels, entries,buttons    def button_click(self):        pass        # If button is clicked, run this method and open window 2class Window2:    def __init__(self, master):        #create buttons,entries,etc    def button_method(self):        #run this when button click to close window        self.master.destroy()def main(): #run mianloop     root = tk.Tk()    app = Window1(root)    root.mainloop()if __name__ == '__main__':    main()

Usually tk programs with multiple windows are multiple big classes and in the __init__ all the entries, labels etc are created and then each method is to handle button click events

There isn't really a right way to do it, whatever works for you and gets the job done as long as its readable and you can easily explain it because if you cant easily explain your program, there probably is a better way to do it.

Take a look at Thinking in Tkinter.