Here we begin the literate exposition of the actual code. First is a prologue directing the reader back to this documentation.
"""fontselect.py: FontSelect, a font selector widget for Tkinter.
For documentation, see:
http://www.nmt.edu/tcc/help/lang/python/examples/fontselect/
"""
Next, the imported modules: the Tkinter
widget set, and its related tkFont module
containing the font-related functions. The Dialog module is another Tkinter accessory module that makes it easy
to construct a pop-up dialog window.
#================================================================ # Imports #---------------------------------------------------------------- from Tkinter import * import tkFont import Dialog
We also use a ScrolledList widget, described
elsewhere, to hold the list of families and its associated
scrollbar. See the separate document, ScrolledList: A Tkinter
scrollable list widget.
import scrolledlist
The manifest constants LISTBOX_HEIGHT and
LISTBOX_WIDTH are the default number of
lines and line widths in the font family listbox.
SAMPLE_TEXT is the initial sample text,
and DEFAULT_SIZE is the starting text size.
#================================================================ # Manifest constants #---------------------------------------------------------------- LISTBOX_HEIGHT = 15 LISTBOX_WIDTH = 30 SAMPLE_TEXT = "0O 1lI| ABC abc" DEFAULT_SIZE = 14 DEFAULT_FAMILY = "helvetica"
There are a lot of widgets inside a widget. 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
the FamilyPicker needs when the family is
changed, and when that function is called, it just passes
the newly chosen family down to the Controls sub-widget.
In order to make class FontSelect act like
any other widget, we declare the class to inherit from
Tkinter's Frame widget.
class FontSelect(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 widget in your Tkinter application”.
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
.familyPicker and .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 ]
"""