When run, the Hye button here prints to stdout and the Bye button closes and exits
the GUI, much as before:
C:\...\PP4E\Gui\Intro> python gui7.py
Hello number 1
Hello number 2
Hello number 3
Hello number 4
Also as before, self.data retains state between events, and callbacks are routed to the
self.message method within this class. Unlike before, the HelloPackage class is not itself
a kind of Frame widget. In fact, it’s not a kind of anything—it serves only as a generator
of namespaces for storing away real widget objects and state. Because of that, widgets
are attached to a self.top (an embedded Frame), not to self. Moreover, all references
to the object as a widget must descend to the embedded frame, as in the top.main
loop call to start the GUI at the end of the script.
This makes for a bit more coding within the class, but it avoids potential name clashes
with both attributes added to self by the tkinter framework and existing tkinter widget
methods. For instance, if you define a config method in your class, it will hide the
config call exported by tkinter. With the standalone class package in this example, you
get only the methods and instance attributes that your class defines.
In practice, tkinter doesn’t use very many names, so this is not generally a big con-
cern.‡ It can happen, of course; but frankly, I’ve never seen a real tkinter name clash in
widget subclasses in some 18 years of Python coding. Moreover, using standalone
classes is not without other downsides. Although they can generally be attached and
subclassed as before, they are not quite plug-and-play compatible with real widget
objects. For instance, the configuration calls made in Example 7-21 for the Frame sub-
class fail in Example 7-25.
Example 7-25. PP4E\Gui\Intro\gui7b.py
from tkinter import *
from gui7 import HelloPackage # or get from gui7c--getattr added
frm = Frame()
frm.pack()
Label(frm, text='hello').pack()
part = HelloPackage(frm)
‡ If you study the tkinter module’s source code (today, mostly in file init.py in Lib\tkinter), you’ll notice
that many of the attribute names it creates start with a single underscore to make them unique from yours;
others do not because they are potentially useful outside of the tkinter implementation (e.g., self.master,
self.children). Curiously, at this writing most of tkinter still does not use the Python “pseudoprivate
attributes” trick of prefixing attribute names with two leading underscores to automatically add the enclosing
class’s name and thus localize them to the creating class. If tkinter is ever rewritten to employ this feature,
name clashes will be much less likely in widget subclasses. Most of the attributes of widget classes, though,
are methods intended for use in client scripts; the single underscore names are accessible too, but are less
likely to clash with most names of your own.
Reusable GUI Components with Classes | 409