Next / Previous / Contents / Shipman's homepage

7.3. Controls._createButtons(): Lay out the small controls frame

This method creates and grids all the widgets inside the self.buttons frame, as well as their control variables.

fontselect.py
    def _createButtons(self):
        """Create all the widgets and control variables in self.buttons.
        """

        #-- 1 --
        # [ self.buttons  :=  self.buttons with a new Label added and
        #                     gridded
        #   self.sizeLabel  :=  that Label ]
        self.sizeLabel = tk.Label(self.buttons,
            font=self.fontSelect.regularFont,
            text="Size:")
        colx = 0
        self.sizeLabel.grid(row=0, column=colx)

The size field has a control variable attached. It also has event bindings for either Return or the FocusOut event that occurs when the user tabs out of the field.

The self._setFont() method is a general-purpose handler. Whenever it is called, it assembles all the font options and, assuming they are valid, changes the current font and calls the observer function. See Section 7.4, “Controls._setFont(): Font change handler”.

fontselect.py
        #-- 2 --
        # [ self.buttons  :=  self.buttons with a new Entry added
        #       and gridded, with a string control variable, that
        #       calls self._setFont on Return or Tab keypresses
        #   self.sizeField  :=  that Entry
        #   self._sizeText  :=  that control variable ]
        self._sizeText = tk.StringVar()
        self._sizeText.set(DEFAULT_SIZE)
        self.sizeField = tk.Entry(self.buttons,
            font=self.fontSelect.regularFont,
            width=4,
            textvariable=self._sizeText)
        colx  +=  1
        self.sizeField.grid(row=0, column=colx)

These two .bind() calls set up the widget so that ._setFont() will be called if the user either hits the Enter key (whose keyname is Return, not Enter), or tabs out of the field. The latter event is called FocusOut because tabbing out of a field causes it to lose keyboard focus.

fontselect.py
        self.sizeField.bind("<KeyPress-Return>",
                              self._setFont)
        self.sizeField.bind("<FocusOut>", self._setFont)

        #-- 3 --
        # [ self.buttons  :=  self.buttons with a new Button added
        #       and gridded, that calls self._setFont when clicked
        #   self.sizeButton  :=  that Button ]
        self.sizeButton = tk.Button(self.buttons,
            text="Set\nsize",
            font=self.fontSelect.regularFont,
            command=self._setFont)
        colx  +=  1
        self.sizeButton.grid(row=0, column=colx)

So that the user sees the size label, size entry, and size button as a group, we want a little extra space to be allocated to the next column inside this frame. This takes two steps. First, we use .columnconfigure to add some extra space within that column. Details are in the section on “Configuring column and row sizes” in the Tkinter reference.

However, this isn't enough. Tkinter will ignore this column configuration unless there is at least one widget in that column. So we also create an empty Frame there.

fontselect.py
        #-- 4 --
        # [ self.buttons  :=  self.buttons with column (colx+1)
        #       made stretchable
        #   colx  +:=  1 ]
        colx  +=  1
        self.buttons.columnconfigure(colx, pad=10)
        self.spacer = tk.Frame(self.buttons)
        self.spacer.grid(row=0, column=colx)

We want the boldface and italic buttons to look like the regular font, only bolded and italicized. We use the .copy() method on self.fontSelect.regularFont to get a copy of that font, then use the .configure method on the copy to change its weight or slant.

Also, we use a medium gray selectcolor, overriding the rather alarming default red color that shows on a selected push-push button.

To make push-push buttons (click to set, click again to reset) for the controls for boldface and italics, we use a Checkbutton widget with the attribute indicatoron=0.

fontselect.py
        #-- 5 --
        # [ self.buttons  :=  self.buttons with a Checkbutton added
        #       and gridded, with an integer control variable
        #   self.boldButton  :=  that Checkbutton
        #   self._isBold    :=  that control variable ]
        self._isBold = tk.IntVar()
        self.boldFont = self.fontSelect.regularFont.copy()
        self.boldFont.configure(weight=tkFont.BOLD)
        self.boldButton = tk.Checkbutton(self.buttons,
            command=self._setFont,
            variable=self._isBold,
            selectcolor="#bbbbbb",
            indicatoron=0,
            font=self.boldFont,
            text="Bold")
        colx  +=  1
        self.boldButton.grid(row=0, column=colx)

        #-- 6 --
        # [ self.buttons  :=  self.buttons with a Checkbutton added
        #       and gridded, with an integer control variable
        #   self.italicButton  :=  that Checkbutton
        #   self._isItalic  :=  that control variable ]
        self._isItalic = tk.IntVar()
        self.italicFont = self.fontSelect.regularFont.copy()
        self.italicFont.configure(slant=tkFont.ITALIC)
        self.italicButton = tk.Checkbutton(self.buttons,
            command=self._setFont,
            variable=self._isItalic,
            selectcolor="#bbbbbb",
            indicatoron=0,
            font=self.italicFont,
            text="Italic")
        colx  +=  1
        self.italicButton.grid(row=0, column=colx)