Next / Previous / Contents / Shipman's homepage

9. PageTurner.__createButtons(): Create the controls

This method creates a Frame containing all the controls, and returns that frame to the caller for gridding.

pageturner.py
# - - -   P a g e T u r n e r . _ _ c r e a t e B u t t o n s   - - -

    def __createButtons ( self ):
        """Create the frame containing all the controls.

          [ return a new Frame containing self's control widgets ]
        """

All the widgets in the control frame are arranged in one horizontal row. However, we want some of them all the way to the left of the frame and some all the way to the right. This cannot be done just by using sticky=W on the first group and sticky=E for the rest: the sticky attribute affects only where widgets are placed within their columns, but it does not make the columns stretchable.

In order to make columns expandable, it is necessary to call the .columnconfigure() method on the parent widget and use a weight=N argument to specify where the extra space will be distributed. To get the positioning we want, we insert a dummy column between the left-hand and right-hand groups of controls, assign it weight=10000 with the .columnconfigure method, and give the other columns weight=1.

Here, then, is a list of the columns gridded inside the control frame, and their contents.

ColumnAttributePurpose
0.__pageLabelThe word “Page”.
1.pageNoEntry Entry widget to display the current page number and allow the user to modify it. The associated control variable is .__pageNoVar.
2.__ofLabelThe word “of”.
3.nPagesLabel Displays the total number of pages. The associated control variable is .__nPagesVar.
4 Dummy column to take up the space between the left-hand and right-hand control groups.
5.prevButton The “Previous page” button.
6.nextButton The “Next page” button.

First we create the frame to be returned to the caller.

pageturner.py
        #-- 1 --
        # [ self     :=  self with a new Frame added
        #   buttons  :=  that new Frame ]
        buttons  =  Frame ( self )

In order for the .pageNoEntry widget to respond to a user's changing the page number, it must have an event binding for the Enter key, which is a "<KeyPress-Return"> event. For the handler that is invoked when the user edits self.pageNoEntry, see Section 10, “PageTurner.__pageNoHandler(): Jump to a user-selected page”.

pageturner.py
        #-- 2 --
        # [ buttons  :=  buttons with a Label added containing "Page " ]
        self.__pageLabel  =  Label ( buttons, text="Page " )
        colx  =  0
        self.__pageLabel.grid ( row=0, column=colx )
        buttons.columnconfigure(colx, weight=1)

        #-- 3 --
        # [ buttons  :=  buttons with an Entry added with a StringVar
        #       control variable, and a handler that turns to the
        #       given page when the user presses Enter
        #   self.pageNoEntry  :=  that Entry
        #   self.__pageNoVar  :=  that StringVar
        self.__pageNoVar  =  StringVar()
        self.__pageNoVar.set("0")
        self.pageNoEntry  =  Entry ( buttons, relief=SUNKEN, width=3,
            textvariable=self.__pageNoVar )
        self.pageNoEntry.bind ( "<KeyPress-Return>",
                                self.__pageNoHandler )
        colx  +=  1
        self.pageNoEntry.grid ( row=0, column=colx )
        buttons.columnconfigure(colx, weight=1)

        #-- 4 --
        # [ buttons  :=  buttons with a Label added containing " of " ]
        self.__ofLabel  =  Label ( buttons, text=" of " )
        colx  +=  1
        self.__ofLabel.grid ( row=0, column=colx )
        buttons.columnconfigure(colx, weight=1)

        #-- 5 --
        # [ buttons  :=  buttons with a Label added with a StringVar
        #             control variable
        #   self.nPagesLabel  :=  that Label
        #   self.__nPagesVar  :=  that StringVar ]
        self.__nPagesVar  =  StringVar()
        self.__nPagesVar.set("0")
        self.nPagesLabel  =  Label ( buttons, relief=FLAT, width=3,
            textvariable=self.__nPagesVar )
        colx  +=  1
        self.nPagesLabel.grid ( row=0, column=colx )
        buttons.columnconfigure(colx, weight=1)

At this point we allocate the dummy column and give it a huge weight configuration so it will absorb the remaining space.

pageturner.py
        #-- 6 --
        # [ buttons  :=  buttons with an empty column that
        #                expands by a factor of 10000 ]
        colx  +=  1
        buttons.columnconfigure(colx, weight=10000)

The “Previous page” and “Next page” buttons are both initially disabled; they will be enabled when the first content page is added. For the button handlers, see Section 11, “PageTurner.__prevHandler(): Go to previous page” and Section 12, “PageTurner.__nextHandler(): Go to next page”.

pageturner.py
        #-- 7 --
        # [ buttons  :=  buttons with a new Button added that moves to
        #             the previous page
        #   self.prevButton  :=  that Button ]
        self.prevButton  =  Button ( buttons, text="Previous page",
            command=self.__prevHandler, state=DISABLED )
        colx  +=  1
        self.prevButton.grid ( row=0, column=colx, sticky=E )
        buttons.columnconfigure(colx, weight=1)

        #-- 8 --
        # [ buttons  :=  buttons with a new Button added that moves to
        #                the next page
        #   self.nextButton  :=  that Button ]
        self.nextButton  =  Button ( buttons, text="Next page",
            command=self.__nextHandler, state=DISABLED )
        colx  +=  1
        self.nextButton.grid ( row=0, column=colx, sticky=E )
        buttons.columnconfigure(colx, weight=1)

All that remains is to return the completed frame to the caller.

pageturner.py
        #-- 9 --
        return buttons