The BrowseEntry Widget

BrowseEntry is a composite widget created to be like a combo box (also known as a drop-down listbox on some platforms) using an Entry widget, a Listbox, and a small arrow button. The combination of these three widgets in the BrowseEntry is very powerful.

Before we list the options and methods for a BrowseEntry, let's look at an example:

use Tk; use Tk::ROText; use Tk::BrowseEntry; $mw = MainWindow->new(-title => "Text search using BrowseEntry"); # Create Browse Entry to enter search text in, and save off # already entered text that you've searched for. $f = $mw->Frame(-relief => 'ridge', -borderwidth => 2) ->pack(-fill => 'x'); # Use ROText so user can't change speech $t = $mw->Scrolled('ROText', -scrollbars => 'osoe') ->pack(-expand => 1, -fill => 'both'); $t->insert('end', <<'EOD' "Give Me Liberty or Give Me Death" March 23, 1775 By Patrick Henry No man thinks more highly than I do of the patriotism, as well as abilities, of the very worthy gentlemen who have just addressed the house. But different <snipped...> I know not what course others may take; but as for me, give me liberty or give me death! EOD ); # define a new tag to use on selected text # (making it look just like normal selection) # This way the Text widget doesn't need focus to show selection $t->tagConfigure('curSel', -background => $t->cget(-selectbackground), -borderwidth => $t->cget(-selectborderwidth), -foreground => $t->cget(-selectforeground)); my $search_string = ""; # If user selects item from list manually, invoke do_search $be = $f->BrowseEntry(-variable => \$search_string, -browsecmd => \&do_search)->pack(-side => 'left'); # If user types in word and hits return, invoke do_search $be->bind("<Return>", \&do_search); $be->focus; # Start w/focus on BrowseEntry # Clicking the Search button will invoke do_search $f->Button(-text => 'Search', -command => \&do_search) ->pack(-side => 'left'); $f->Button(-text => 'Exit', -command => \&do_exit) ->pack(-side => 'right'); sub do_search {
 # Add search string to list if it's not already there if (! exists $searches{$search_string}) {
 $be->insert('end', $search_string);
}
$searches{$search_string}++; # Calculate where to search from, and what to highlight next my $startindex = 'insert'; if (defined $t->tagRanges('curSel')) {
 $startindex = 'curSel.first + 1 chars';
}
my $index = $t->search('-nocase', $search_string, $startindex); if ($index ne '') {
 $t->tagRemove('curSel', '1.0', 'end'); my $endindex = "$index + " . (length $search_string) . " chars"; $t->tagAdd('curSel', $index, $endindex); $t->see($index);
}
else {
 $mw->bell;
}
$be->selectionRange(0, 'end'); # Select word we just typed/selected
}
# print stats on searching before we exit. sub do_exit {
 print "Count Word\n"; foreach (sort keys %searches) {
 print "$searches{$_} $_\n";
}
exit;
}
MainLoop;

Take a look at Figure 23-13 to see the screenshot of this application. The BrowseEntry is in the upper-left corner. We have shown it with the list part of the BrowseEntry down (after the down arrow button has been pressed). Figure 23-13

Figure 23-13. BrowseEntry used to perform searches in a Text widget

In this example, we are using the BrowseEntry with mostly default settings. We added a callback so that when the user selected an entry from the list manually, the search subroutine was invoked as well. The easiest way to know what the user has selected/typed is to use the -variable option. Most of the code for this example has to do with figuring out where the word is in the Text widget.

The BrowseEntry supports all the options a LabEntry does (see "Label and Entry Widgets"), except -textvariable. Additional BrowseEntry options are:

  • -arrowimage => image
  • This option changes the picture on the little button.
  • -browsecmd => callback
  • This callback will be invoked whenever the user selects something from the list. BrowseEntry already performs the work to display the new selection in the edit box.
  • -choices => list
  • You can put choices in the list using this option. Examples are: -choices => [ qw/one two three/ ] or -choices => @init_choices. You can also add items to the list using the insert method ($be->insert('end', 'newchoice'); ).
  • -listcmd => callback
  • Specify a callback to be invoked when the arrow button is pushed. This will be called before the list is displayed, so if you need to change the contents of the drop-down list, this is a great place to do so.
  • -listwidth => amount
  • The width of the popup listbox. The listbox will not automatically grow to fit your choices if you have long strings in it.
  • -variable => $scalar
  • Place the user's selection in $scalar.
  • -state => 'normal' | 'readonly' | 'disabled'
  • A state of 'normal' that the user can type in new entries and select entries from the list. A 'readonly' state limits the user to only selecting items from the list. A state of 'disabled' will not allow any interaction with the user at all.

In addition to all the methods of Tk::Entry, the BrowseEntry widget supports its own insert and delete methods:

$be->insert('index', 'string'); $be->delete('index1', 'index2');

The insert method adds a new item into the list at the specified index. The delete method removes list entries that are between the two indexes.