Previous section   Next section

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

Table of Contents
Chapter 32.  The Listbox Widget

Using Listboxes

The lines in a listbox are indexed from zero. The keyword index end addresses the last line. Other indices are described on page 445. The most common programming task for a listbox is to insert text. If your data is in a list, you can loop through the list and insert each element at the end:

foreach item $list {
     $listbox insert end $item

You can insert several items at once. The next command uses eval to concatenate the list onto a single insert command:

eval {$listbox insert end}$list

It is also common to react to mouse clicks on a listbox, although the default bindings handle most of the details of selecting items. The nearest operation finds the listbox entry that is closest to a mouse event. If the mouse is clicked beyond the last element, the index of the last element is returned:

set index [$list nearest $y]

Example 32-1 displays two listboxes. The Scrolled_Listbox procedure on page 432 is used to put scrollbars on the listboxes. When the user clicks on an item in the first listbox, it is copied into the second listbox. When an item in the second listbox is selected, it is removed. This example shows how to manipulate items selected from a listbox:

Example 32-1 Choosing items from a listbox.


proc List_Select { parent values } {
   # Create two lists side by side
   frame $parent
   set choices [Scrolled_Listbox $parent.choices \
       -width 20 -height 5 ]
   set picked [Scrolled_Listbox $parent.picked \
       -width 20 -height 5]
   pack $parent.choices $parent.picked -side left \
       -expand true -fill both

   # Selecting in choices moves items into picked
   bind $choices <ButtonRelease-1> \
      [list ListTransferSel %W $picked]

   # Selecting in picked deletes items
   bind $picked <ButtonRelease-1> \
      {ListDeleteSel %W %y}

   # Insert all the choices
   foreach x $values {
      $choices insert end $x
proc ListTransferSel {src dst} {
   foreach i [$src curselection] {
      $dst insert end [$src get $i]
proc ListDeleteSel {w y} {
   foreach i [lsort -integer -decreasing [$w curselection]] {
      $w delete $i
proc List_SelectValues {parent} {
   set picked $parent.picked.list
   set result {}
   foreach i [$w curselection] {
      lappend $result [$w get $i]
List_Select .f {apples oranges bananas \
             grapes mangos peaches pears}
pack .f -expand true -fill both

Bindings are created to move items from $choices to $picked, and to delete items from $picked. Most of the work of selecting things in the listbox is done by the built-in bindings on the Listbox binding tag. The different selection models are described on page 448. Those bindings are on <ButtonPress-1> and <B1-Motion>. The selection is complete by the time the <ButtonRelease-1> event occurs. Consider the <ButtonRelease-1> binding for $choices:

bind $choices <ButtonRelease-1> \
     [list ListTransferSel %W $picked]

The list command is used to construct the Tcl command because we need to expand the value of $picked at the time the binding is created. The command will be evaluated later at the global scope, and picked will not be defined after the List_Select procedure returns. Or, worse yet, an existing global variable named picked will be used, which is unlikely to be correct!

Short procedures are used to implement the binding commands. This style has two advantages. First, it confines the % substitutions done by bind to a single command. Second, if there are any temporary variables, such as the loop counter i, they are hidden within the scope of the procedure.

The ListTransferSel gets the list of all the selected items and loops over this list to insert them into the other list. The ListDeleteSel procedure is similar. However, it sorts the selection indices in reverse order. It deletes items from the bottom up so the indices remain valid throughout the process.

Programming Listboxes

The listbox operations use indices to reference lines in the listbox. The lines are numbered starting at zero. Keyword indices are also used for some special lines. The listbox keeps track of an active element, which is displayed with underlined text. There is also a selection anchor that is used when adjusting selections. Table 32-1 summarizes the keywords used for indices.

Table 32-1. Listbox indices
0Index of the first line.
activeThe index of the activated line.
anchorThe index of the anchor point of the selection.
endIndex of the last line.
numberIndex a line, counting from zero.
@x,yThe line closest to the specified X and Y coordinates.

Table 32-2 presents the operations for programming a listbox. In the table, $w is a listbox widget. Most of the operations have to do with the selection, and these operations are already programmed by the default bindings for the Listbox widget class:

Table 32-2. Listbox operations.
$w activate indexActivates the specified line.
$w bbox indexReturns the bounding box of the text in the specified line in the form: xoff yoff width height.
$w cget optionReturns the value of the configuration option.
$w configure ...Queries or modifies the widget configuration.
$w curselectionReturns a list of indices of the selected lines.
$w delete first ?last?Deletes the lines from first to last, including the line at last. The line at first is deleted if last is not given.
$w get first ?last?Returns the lines from first to last as a list.
$w index indexReturns the numerical index corresponding to index.
$w insert index ?string string string ...?Inserts the string items before the line at index. If index is end, then append the items.
$w nearest yReturns the index of the line closest to the widget-relative Y coordinate.
$w scan mark x yStarts a scroll operation. x and y are widget-relative screen coordinates.
$w scan dragto x yScrolls from previous mark position.
$w see indexAdjusts the display so the line at index is visible.
$w selection anchor indexAnchors the selection at the specified line.
$w selection clear start ?end?Clears the selection.
$w selection includes indexReturns 1 if the line at index is in the selection.
$w selection set start ?end?Selects the lines from start to end.
$w xviewReturns the offset and span of visible contents. These are both real numbers between 0 and 1.
$w xview indexShifts the display so the character at index is at the left edge of the display.
$w xview moveto fractionShifts the display so that fraction of the contents are off the left edge of the display.
$w xview scroll num whatScrolls the contents horizontally by the specified number of what, which can be units or pages.
$w yviewReturns the offset and span of visible contents. These are both real numbers between 0 and 1.
$w yview indexShifts the display so the line at index is at the top edge of the display.
$w yview moveto fractionShifts the display so that fraction of the contents are off the top of the display.
$w yview scroll num whatScrolls the contents vertically by the specified number of what, which can be units or pages.

      Previous section   Next section