The GUIs we have built so far have not been particularly well structured. Most of the code to construct them has not been modularized in functions, and they have relied on global variables. We can get away with this for very small examples, but if we try to build larger applications this way, they will be difficult to understand and debug.
For this reason, almost all real GUIs are built using classes and objects that tie models, views, and controllers together in one tidy package. In the counter shown next, for example, the application’s model is a member variable of class Counter, accessed using self.state, and its controllers are the methods up_click and quit_click.
| import tkinter |
| |
| class Counter: |
| """A simple counter GUI using object-oriented programming.""" |
| def __init__(self, parent): |
| |
| """Create the GUI.""" |
| |
| # Framework. |
| self.parent = parent |
| self.frame = tkinter.Frame(parent) |
| self.frame.pack() |
| |
| # Model. |
| self.state = tkinter.IntVar() |
| self.state.set(1) |
| |
| # Label displaying current state. |
| self.label = tkinter.Label(self.frame, textvariable=self.state) |
| self.label.pack() |
| |
| # Buttons to control application. |
| self.up = tkinter.Button(self.frame, text='up', command=self.up_click) |
| self.up.pack(side='left') |
| |
| self.right = tkinter.Button(self.frame, text='quit', |
| command=self.quit_click) |
| self.right.pack(side='left') |
| |
| def up_click(self): |
| """Handle click on 'up' button.""" |
| |
| self.state.set(self.state.get() + 1) |
| |
| |
| def quit_click(self): |
| """Handle click on 'quit' button.""" |
| |
| self.parent.destroy() |
| if __name__ == '__main__': |
| |
| window = tkinter.Tk() |
| myapp = Counter(window) |
| window.mainloop() |