There are a lot of widgets inside awidget. To simplify the spatial and logical organization, we won't deal with all the widgets at the top level. Instead, we'll use a “frames within frames within frames” technique so that the layout and control linkages at each level are relatively simple.
Hence, at this level, our grid plan has only two cells: the family listbox (and associated label) in row 0, column 0, and everything else in row 0, column 1.
To make this division of function crystal-clear, we'll move the logic for each of those two groups into separate classes:
class FamilyPicker contains the family
listbox and associated label. It will have a
callback linkage, a function that will be called each
time the user clicks on a family name.
class Controls contains everything
else. It will have a method called
.setFont() that changes the current family.
So the work of this class is very simple. It creates and
grids the two sub-widgets. It provides the function that
FamilyPicker needs when the family is
changed, and when that function is called, it just passes
the newly chosen family down to the
In order to make class
FontSelect act like
any other widget, we declare the class to inherit from
Tkinter's Frame widget.
class FontSelect(tk.Frame): """A compound widget for selecting fonts.
Here are the Cleanroom intended functions for the constructor and
methods, and declarations of exported attributes. The calling
sequence for the
observer function is discussed
in Section 3, “Using the
FontSelect widget in your Tkinter
Exports: FontSelect(master, font=None, listCount=None, observer=None): [ (master is a Frame or None) and (font is a tkFont.Font or None) and (listCount is an integer, defaulting to LISTBOX_HEIGHT) and (observer is a function to be called when the font changes) -> master := master with a new FontSelect widget added but not gridded, with that font, list count, and observer function return that widget ] .scrollList: [ a ScrolledList containing the family names ] .get(): [ if a font has been selected -> return that font as a tkFont.Font object else -> return None ] .getName(): [ if a font has been selected -> return a string describing the actual font else -> return None ] .addObserver(f): [ self := self with a new observer function added ]
So that our subwidgets have access to the fonts created at this level, we make these fonts public attributes.
.regularFont: [ a tkFont.Font for general purposes ] .listFont: [ if a font option was passed to the constructor -> that option's value else -> self.regularFont ]
Attributes inside the class include the sub-widgets
.controls, and also three fonts we'll need.
Internal widgets: .familyPicker: [ a FamilyPicker for picking the font family ] .controls: [ a Controls widget containing other controls ] State/Invariants: ._listCount: [ if a listCount option was passed to the constructor -> that option's value else -> LISTBOX_HEIGHT ] ._observerList: [ a list containing all observer callback functions for self ] """