Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 30.  Scrollbars

The Scrollbar Protocol

When the user manipulates the scrollbar, it calls its registered command with some additional parameters that indicate what the user said to do. The associated widget responds to this command (e.g., its xview operation) by changing its display. After the widget changes its display, it calls the scrollbar by using its registered xscrollcommand or yscrollcommand (e.g., the set operation) with some parameters that indicate the new relative size and position of the display. The scrollbar updates its appearance to reflect this information.

The protocol supports widgets that change their display by themselves, such as when more information is added to the widget. Scrollable widgets also support a binding to <B2-Motion> (i.e., "middle drag") that scrolls the widget. When anything happens to change the view on a widget, the scrollable widgets use their scroll commands to update the scrollbar.

The Scrollbar set Operation

The scrollbar set operation takes two floating point values between zero and one, first and last, that indicate the relative position of the top and bottom (or left and right) of the widget's display. The scrollable widget adds these values when they use their yscrollcommand or xscrollcommand. For example, the text widget would issue the following command to indicate that the first quarter of the widget is displayed:

.yscroll set 0.0 0.25

If the two values are 0.0 and 1.0, it means that the widget's contents are fully visible, and a scrollbar is not necessary. You can monitor the protocol by using a Tcl wrapper, Scroll_Set, instead of the set operation directly. Scroll_Set waits for the scrollbar to be necessary before mapping it with a geometry manager command. It is not safe to unmap the scrollbar because that can change the size of the widget and create the need for a scrollbar. That leads to an infinite loop.

Example 30-2 Scroll_Set manages optional scrollbars.
proc Scroll_Set {scrollbar geoCmd offset size} {
   if {$offset != 0.0 || $size != 1.0} {
      eval $geoCmd     ;# Make sure it is visible
   $scrollbar set $offset $size

Scroll_Set takes a geometry management command as an argument, which it uses to make the scrollbar visible. Example 30-3 uses Scroll_Set with a listbox. Note that it does not grid the scrollbars directly. Instead, it lets Scroll_Set do the geometry command the first time it is necessary.

Example 30-3 Listbox with optional scrollbars.


proc Scrolled_Listbox { f args } {
   frame $f
   listbox $f.list \
      -xscrollcommand [list Scroll_Set $f.xscroll \
         [list grid $f.xscroll -row 1 -column 0 -sticky we]] \
      -yscrollcommand [list Scroll_Set $f.yscroll \
         [list grid $f.yscroll -row 0 -column 1 -sticky ns]]
   eval {$f.list configure}$args
   scrollbar $f.xscroll -orient horizontal \
      -command [list $f.list xview]
   scrollbar $f.yscroll -orient vertical \
      -command [list $f.list yview]
   grid $f.list -sticky news
   grid rowconfigure $f 0 -weight 1
   grid columnconfigure $f 0 -weight 1
   return $f.list

Scrolled_Listbox takes optional parameters for the listbox. It uses eval to configure the listbox with these arguments. The style of using eval shown here is explained in Example 10-3 on page 127. Example 43-4 on page 596 associates two listboxes with one scrollbar.

The xview and yview Operations

The xview and yview operations are designed to be called from scrollbars, and they work the same for all scrollable widgets. You can use them to scroll the widgets for any reason, not just when the scrollbar is used. The following examples use a text widget named .text for illustration.

The xview and yview operations return the current first and last values that would be passed to a scrollbar set command:

.text yview
=> 0.2 0.55

When the user clicks on the arrows at either end of the scrollbar, the scrollbar adds scroll num units to its command, where num is positive to scroll down, and negative to scroll up. Scrolling up one line is indicated with this command:

.text yview scroll -1 units

When the user clicks above or below the elevator of the scrollbar, the scrollbar adds scroll num pages to its command. Scrolling down one page is indicated with this command:

.text yview scroll 1 pages

You can position a widget so that the top (or left) edge is at a particular offset from the beginning of the widget's contents. The offset is expressed as a floating point value between zero and one. To view the beginning of the contents:

.text yview moveto 0.0

If the offset is 1.0, the last part of the widget content's is displayed. The Tk widgets always keep the end of the widget contents at the bottom (or right) edge of the widget, unless the widget is larger than necessary to display all the contents. You can exploit this with the one-line entry widget to view the end of long strings:

.entry xview moveto 1.0

The Tk 3.6 Protocol

The protocol between the scrollbar and its associated widget changed in Tk 4.0. The scrollbar is backward compatible. The Tk 3.6 protocol had four parameters in the set operation: totalUnits, windowUnits, firstUnit, and lastUnit. If a scrollbar is updated with this form of a set command, then the get operation also changes to return this information. When the scrollbar makes the callback to the other widget (e.g., an xview or yview operation), it passes a single extra parameter that specifies what unit to display at the top (left) of the associated widget. The Tk widgets' xview and yview operations are also backward compatible with this interface.

      Previous section   Next section