OOP features can be applied to GUI models: specializing widgets by inheritance.
Example 7-18 builds the window in Figure 7-19.
Example 7-18. PP4E\Gui\Intro\gui5.py
from tkinter import *
class HelloButton(Button):
def init(self, parent=None, config): # add callback method
Button.init(self, parent, config) # and pack myself
self.pack() # could config style too
self.config(command=self.callback)
def callback(self): # default press action
print('Goodbye world...') # replace in subclasses
self.quit()
if name == 'main':
HelloButton(text='Hello subclass world').mainloop()
Figure 7-19. A button subclass in action
This example isn’t anything special to look at: it just displays a single button that, when
pressed, prints a message and exits. But this time, it is a button widget we created on
our own. The HelloButton class inherits everything from the tkinter Button class, but
adds a callback method and constructor logic to set the command option to
self.callback, a bound method of the instance. When the button is pressed this time,
the new widget class’s callback method, not a simple function, is invoked.
The config argument here is assigned unmatched keyword arguments in a dictionary,
so they can be passed along to the Button constructor. The config in the Button
constructor call unpacks the dictionary back into keyword arguments (it’s actually
optional here, because of the old-style dictionary widget call form we met earlier, but
doesn’t hurt). We met the config widget method called in HelloButton’s constructor
earlier; it is just an alternative way to pass configuration options after the fact (instead
of passing constructor arguments).
Standardizing Behavior and Appearance
So what’s the point of subclassing widgets like this? In short, it allows sets of widgets
made from the customized classes to look and act the same. When coded well, we get
both “for free” from Python’s OOP model. This can be a powerful technique in larger
programs.
Customizing Widgets with Classes | 401