scope of the module file containing the widget calls. This works for simple GUIs but
can make for brittle code when building up larger GUI structures.
But by subclassing Frame as we’ve done here, the class becomes an enclosing context
for the GUI:
- Widgets are added by attaching objects to self, an instance of a Frame container
subclass (e.g., Button). - Callback handlers are registered as bound methods of self, and so are routed back
to code in the class (e.g., self.message). - State information is retained between events by assigning to attributes of self,
visible to all callback methods in the class (e.g., self.data). - It’s easy to make multiple copies of such a GUI component, even within the same
process, because each class instance is a distinct namespace. - Classes naturally support customization by inheritance and by composition
attachment.
In a sense, entire GUIs become specialized Frame objects with extensions for an appli-
cation. Classes can also provide protocols for building widgets (e.g., the
make_widgets method here), handle standard configuration chores (like setting window
manager options), and so on. In short, Frame subclasses provide a simple way to or-
ganize collections of other widget-class objects.
Attaching Class Components
Perhaps more importantly, subclasses of Frame are true widgets: they can be further
extended and customized by subclassing and can be attached to enclosing widgets. For
instance, to attach the entire package of widgets that a class builds to something else,
simply create an instance of the class with a real parent widget passed in. To illustrate,
running the script in Example 7-21 creates the window shown in Figure 7-21.
Example 7-21. PP4E\Gui\Intro\gui6b.py
from sys import exit
from tkinter import * # get Tk widget classes
from gui6 import Hello # get the subframe class
parent = Frame(None) # make a container widget
parent.pack()
Hello(parent).pack(side=RIGHT) # attach Hello instead of running it
Button(parent, text='Attach', command=exit).pack(side=LEFT)
parent.mainloop()
Reusable GUI Components with Classes | 405