Tk::JComboBox - Create and manipulate JComboBox widgets |
Tk::JComboBox - Create and manipulate JComboBox widgets
$jcb = $parent->JComboBox(?options);
JComboBox is a composite widget that contains a text Label or Entry, a Button, and a popup Listbox. It performs the same sort of tasks that can be accomplished by several other Composite widgets. Some such as BrowseEntry and Optionmenu are part of the standard Tk distribution, and there are many others available in CPAN.
JComboBox borrows features from the Java Swing component bearing the same name, but falls short of being a true clone. Many of the methods and the general look and feel should be familiar to java developers. JComboBox also combines several features offered by many of the other ``Combo Box'' implementations, and works in two modes: editable and readonly.
In readonly mode, JComboBox offers similar functionality to Optionmenu. It is basically a labeled button that activates a popup list. An item from the list is displayed on the Button when selected.
When editable, JComboBox somewhat resembles BrowseEntry. That is, the widget is composed of an Entry widget with a Button to the right of it. As in the editable mode, the Button activates a popup Listbox from which a single item can be selected.
For more detailed information on using this widget, refer to the JComboBox tutorial.
You should use caution when configuring JComboBox subwidgets. Extensive configuration changes may result in unexpected or invalid behavior. The subwidgets are advertised to allow for fine tuned configuration of the internal subwidgets, when there no provided options or methods that will do what you need.
This Label is used to display the selected item from the popup Listbox. This widget and the Button subwidget form the face of the Button that triggers the popup Listbox.
This Entry is used to display the selected item from the popup Listbox, or can accept input that does not appear within the Listbox.
This Label is used to trigger the Popup Listbox, and by default displays a bitmap of a filled triangle that points downward. This subwidget only supports Label options.
This widget contains the Listbox subwidget that displays one or more entries that can be selected for the JComboBox. This is mostly used a container (and an additional way of configuring the Listbox dimensions).
Used to contain one or more entries, one of which can be selected and displayed within the Box subwidget. Note: use caution when using this Subwidget directly. In 804 versions of Tk, Listbox has a memory leak. It's suggested that you use JComboBox methods for adding/deleting/clearing Listbox elements to avoid the leak.
JComboBox supports a long list of options, so to try and break them up a bit I've grouped them in sections. The Basic section contains options that implement or override standard Tk options. or deal with simple things such as colors. The Callback section contains all the options that can have configured Callbacks. The Miscellaneous section contains options that are unique to this widget. These options provide complex functionality that can alter look and feel or provide for initialization shortcuts.
Specifies the normal background color to use when displaying the widget. This color will be applied to all internal widgets as well. For fine-tuned configuration of subwidgets, refer to the -subwidgets option.
Specifies a non-negative value indicated the width of the of the 3-D border to draw around the outside of the widget.
Specifies the mouse cursor to be used for the widget. This cursor will be applied to all internal widgets as well.
Specifies a value to use for sizing the width of the Entry subwidget. The specified value can fall in one of three categories. If a value greater than 0 is specified, then the Entry will use that width regardless of the contents of the Listbox, or values set to the Listbox. If the value is set to 0, then the Entry will be sized large enough to hold its current text. If set to -1, the Entry will be sized to the longest item currently contained within the Listbox. The value defaults to -1, which works well for when the JComboBox contains a fairly static list. Otherwise, a value greater than 0 is recommended.
Specifies the font to use when drawing text inside the widget. This font will be applied to internal widgets that can display a font.
Specifies the foreground color to use for the Entry and Listbox subwidget in either mode.
Specifies the number of spaces (in characters) between the Entry and the Button subwidgets. Default value is 0.
Specifies the width of a rectangular border to insert between the Entry/Button Subwidgets and their container. This can be used to enlarge the height of the JComboBox. It has no default value.
Specifies the border style desired for the widget. Acceptable values are raised, sunken, flat, ridge, solid, and groove. The value indicates how the interior of the widget should appear relative to its exterior; for example, raised means the interior of the widget should appear to protrude from the screen, relative to the exterior of the widget. The default value depends on the mode: groove in readonly mode and sunken in editable mode.
Specifies one of two state values for the JComboBox: normal and disabled. When the state is set to disabled, the event handlers will not respond to user events, and the color of the JComboBox will change depending on the mode. In both modes, -disableforeground will be applied to both the Entry and Button subwidgets' foreground. In editable mode, -disablebackground will be applied to the Entry subwidget's background. The disabled state also causes -takefocus to be set to 0. Changing the state back to the default of normal will reverse these changes to the JComboBox.
Determines whether or not the JComboBox takes focus or not during keyboard traversal. This setting defaults to 1 and is crucial to the JComboBox accepting keyboard events. Regardless of mode, it is the Entry subwidget within the JComboBox that receives the focus, and so it should be the target of any key binding.
Used to pass a scalar reference into the JComboBox that will provide a way of setting and accessing the selected value. This option can be used as an alternative to using the various widget methods because scalar references that are passed are tied to widget methods. Every time the variable is accessed, it is roughly equivalent to calling: getSelectedValue(), and every time the variable is set, it is like calling: setSelected($value, -type = 'value')>.
Because each Listbox entry in JComboBox could represent two pieces of information, it's important to understand precisely what the -textvariable provides access to. Given the following setup:
my $value; my $jcb = $mw->JComboBox( -textvariable => \$value, -choices => [ {-name => 'one', -value => 1}, {-name => 'two', -value => 2}, "three" ], )->pack;
The following should be expected:
$jcb->setSelectedIndex(0); print $value . "\n"; ## prints 1 $jcb->setSelectedIndex(2); print $value . "\n"; ## prints three
And the following would also be expected:
$this = 2; ## changes the selection to "two" $this = "three"; ## changes the selection to "three"
Because no value for ``three'' was specified, the value defaults to ``three'' for the purpose of both examples. Note that the mode may limit what can be set as well. For example, in ``readonly'' mode, the only items that can be selected are those that appear within the Listbox.
Note: Unlike other widgets, -textvariable is tightly controlled within JComboBox and experimentation is recommended if you plan to use it. It can be used as a shortcut for setting/retrieving item values.
Some of the options have changed names since the previous version. -menucreate/-menumodify, for example are now, -popupcreate/-popupmodify. After having now looked at the code for a year or so, the old names felt wrong. After all, it is not a menu that is displayed, its a Listbox, and the two are very different. Because I had a subwidget called Popup, it seemed to make more sense to me for these options to use ``popup'' instead of ``menu''.
Callbacks are passed at least two parameters: $searchStr and $field. searchStr contains the search string. This will be the search pattern. When the -matchcommand is not set, all special regex patterns are escaped, and the search is generally anchored to the start of any string it will compared to. field is a single item within the list that the searchStr is being checked against. It will either be the name, which is the String that appears in the list, or it's value. The value is non-visible element associated with the visible one. A callback should return 1 if the match succeeds, and 0 otherwise.
Refer to the tutorial for more information on this option.
Note for versions prior to 1.12: In prior versions, this callback could be configured to completely replace the internal positioning/configuration of the Popup. This is a good deal of trouble for soneone to go through, and it didn't seem to be a likely need -- espcially given the presence of the -popupmodify option. Developers using this option in older versions, can call $jcb->PopupCreate within their custom -popupcreate callback to get an aproximation of the functionality in 1.12 and beyond. Also in older versions if the JComboBox contained no items or was already being displayed this callback would not be invoked. This is no longer the case.
The options currently include:
-enable - Specifies whether or not to enable autofind or not. The value defaults to 1.
-casesensitive - Specifies whether or not the autofind capability should ignore the case of each keystroke when finding a match in the List. Defaults to 0.
-complete - Specifies whether or not to use auto completion when the JComboBox is in editable mode. Auto completion causes the remainder of an entry to be filled in when a matching entry is found, though the entry is not yet selected. Defaults to 0. Note, this option is ignored regardless of value when the -select option is enabled.
-select - Selects the first item in the list that matches the keystroke (in editable mode), and entry (in readonly mode). Repeated keys/entries will cause the next matching entry to be selected. Defaults to 0. This option takes priority over the -complete option.
-showpopup - Specifies whether or not to display the Popup Listbox when a matching entry is found within the list. Defaults to 1.
More information on this option can be found in the tutorial under Using Autofind.
Specifies whether or not list highlighting should be set. List highlighting is typical on Win32 Combo Box implementations. When the mouse is over a Listbox item, the item appears as though it were selected in the Listbox. A value of 1 enabled the feature, and 0 deactivates it. The default setting is 1.
By default, the width of the Popup is sized to fit the width of the JComboBox. This option allows that behavior to be modified. If defined, the listwidth will be applied to the width of the Listbox, and the width of the Listbox will be the primary factor in sizing the Popup (borderwidth of the Popup, and presence of a scrollbar also will figure into sizing). The default value is -1.
Specifies a maximum number of rows that will be displayed in the Listbox subwidget. If the Listbox contains fewer elements than the specified size, then it will shrink to fit only that number. If there are more elements than the specified maxrows size, then the Listbox will adjust the height to the specified number and use a scrollbar for accessing the other elements. Defaults to 10. Note: if a specified maxrows value causes the Popup to expand beyond the top and bottom of the screen, then the maxrow setting will be overridden automatically so that the popup can be contained within the screen.
Specifies the operating mode of the JComboBox, and can either by readonly, the default, or editable. The mode can currently only be set at Creation time, and cannot be reconfigured. Some options can have subtly different affects depending on the mode. These cases will be noted under the documentation for each option.
When the JComboBox has focus, and the popup is visible, the arrow keys can be used to move the Listbox selection up or down. The Listbox selection is not necessarily equivalent to the JComboBox selection. In Win32 Combo Box implementations, it is common for the up/down keys to also affect the JComboBox selection along with the Listbox selection. This option toggles that behavior. If set to 1 then the arrow keys will treat the previous or next item in the Listbox as the selected item in the JComboBox, and if set to 0, it won't. The default setting is 1.
This option is only used when in editable mode, and generally is exactly the same as the same option for the Entry Widget. It specifies the mode in which validation should operate: none, focus, focusin, focusout, key, or all. It defaults to none. When you want validation, you must explicitly state which mode you wish to use.
In addition, there are two other values: match and cs-match that restrict values to entries that are contained within the internal List. cs-match treats case as significant, and match does not. When used, these options effectively negate the editable mode. When these values are configured, the JComboBox automatically configures its own CALLBACK for the -validatecommand option.
As of version 1.07, setting the -choices option will do more than simply populate the JComboBox Listbox -- it will tie the internal List to the array. This means that as an alternative to using the various public methods, you can use the array as an interface. Changes made to the array will be reflected in the JComboBox, and vice versa.
As of version 1.08, a single array can be associated with multiple JComboBox instances. However, the precise behavior merits further explanation. Not all associated instances have the same relationship with the array. The first instance to be configured with the array becomes the master instance, and all other instances retain roles as observers. When changes are made to the array, both master and observers will be modified to reflect the change. Changes made to the master through its methods will reflected in the array, and those made to observers will not. If the master is reconfigured to use a different choices array, then all of the other observers will automatically be reconfigured as well. If an observer is reconfigured, then it will be the only one to be changed. If the new array is not already associated with other JComboBox instances, then the observer will become the master instance for the new array,
For more details on using this option, refer to the section in the tutorial, Access Through the Choices Array.
-selected => selected
Where selected is a boolean value (true/yes/1) and determines whether or not the list item is the select item within the JComboBox. The default value for this is false. Any subsequent call that uses this option overrides previous ones.
-value => value
Where value is an alternate scalar associated with the List item for times when it's desirable to have a value other than the one displayed (can be useful for database applications).
Example:
$jcb->addItem('Alaska', -value => 'AK', -selected => 1);
-type => type
Where type is either name, which is the displayed text, or value, which is the alternate value associated with the item. If an item in the JComboBox does not have a value defined, then that item's name will be used. Defaults to name.
-mode => mode
Where mode affects how the given string is compared to a list item. Values include: exact, usecase, and ignorecase. exact means that the string must completely match the list item, including case. usecase means that the string must match the beginning of the list item, including its case. ignorecase means that the string must match the beginning of the list item, regardless of the case. Defaults to exact.
Example:
## Finds first matching list item that has a value complete matching AK my $index = $jcb->getItemIndex('AK', -type => 'value'); ## Finds the first matching list item that starts with the letter 'a' my $index = $jcb->getItemIndex('a', -mode => 'usecase'); ## Finds the first matching list item that starts with 'a' or 'A' my $index = $jcb->getItemIndex('a', -mode => 'ignorecase');
-selected => selected
Where selected is a boolean value (true/yes/1) and determines whether or not the list item is the select item within the JComboBox. The default value for this is false. Any subsequent call that uses this option overrides previous ones.
-value => value
Where value is an alternate scalar associated with the List item for times when it's desirable to have a value other than the one displayed (can be useful for database applications).
Example:
The following example produces the same result as the example given for addItem:
$jcb->insertItemAt('end', 'ALASKA', -value => 'AK', -selected => 1);
-type => type
Where type is either name, which is the displayed text, or value, which is the alternate value associated with the item. If an item in the JComboBox does not have a value defined, then that item's name will be used. Defaults to name.
-mode => mode
Where mode affects how the given string is compared to a list item. Values include: exact, usecase, and ignorecase. exact means that the string must completely match the list item, including case. usecase means that the string must match the beginning of the list item, including its case. ignorecase means that the string must match the beginning of the list item, regardless of the case. Defaults to exact.
Like other Combo Box implementations, JComboBox now has a set of Keyboard bindings that provide access to the entries within the popup Listbox. The precise behavior of some of these bindings will depend on JComboBox options such as -autofind, -list highlighting, and -updownselect.
For the editable mode, the default behavior is identical, except that instead of just the first letter, the entire String within the Entry will be used for the search. Refer to the Tutorial documentation on Customizing Interface Behavior for more information. Uses the KeyPress event handler.
There really isn't much in the way of convention or policy on how composite widgets, such as JComboBox should handle events and binding, so JComboBox tries to strike a balance between between simplicity, flexibility, and functionality. Even so, simplicity sometimes takes a back seat to the other two. Let's say that after checking out the options, you decide that none of the built-in behavior provides quite what you need, and you decide that a binding is necessary.
If the binding is not for a key-related event, then I'd suggest that you bind directly to one of JComboBox's Subwidgets. They are all documented. You might consider passing a variable containing the JComboBox instead to your event handler as well, because the first parameter passed to your subroutine will be the Subwidget being bound. Be aware that some of these Subwidget may already be bound internally by JComboBox.
If you are interested in making a key binding, then my best advice would be to bind to the Entry subwidget, since it is the only widget within JComboBox that has been setup to takefocus. It is important to remember that most of the bindings that are listed in this document, are also bound to Entry, so test any binding you do very carefully to ensure that it does what you wish. Here is an example of how a binding for the <Return> (Enter) key might be done (this should work equally well for either mode):
use Tk; use Tk::JComboBox;
my $variable; my $mw = MainWindow->new; my $jcb = $mw->JComboBox( -choices => [ { -name => 'Black', -value => '#000000' }, { -name => 'Blue', -value => '#0000ff' }, { -name => 'Green', -value => '#008000' }, { -name => 'Purple', -value => '#8000ff' }, { -name => 'Red', -value => '#ff0000' }, { -name => 'Yellow', -value => '#ffff00' }], -textvariable => \$variable )->pack; $jcb->Subwidget('Entry')->bind('<Return>', [\&Submit, $jcb]); $jcb->focus;
MainLoop;
sub Submit { my ($entry, $jcb) = @_; print "\nSubmit Called\n"; my $index = $jcb->getSelectedIndex(); print "Index: $index \n"; print "value: " . $jcb->getSelectedValue() . "\n"; print "name: " . $jcb->getItemNameAt($index) . "\n"; print "textvariable: $variable \n"; $done = "done"; }
If JComboBox doesn't fit your needs, you're free to modify the code as you see fit, but before you do, you might consider some of the alternatives that are available on CPAN. Even if none of the others is a perfect fit, it may be closer to what you were looking for, and be easier to modify.
The standard distribution contains two Composites that do some of what JComboBox does: Tk::BrowseEntry and Tk::Optionmenu. BrowseEntry visually resembles JComboBox in editable mode to a certain extent, and Optionmenu is a bit like JComboBox in readonly mode. The main difference is that JComboBox more closely resembles a Win32 Combo Box (Pre-Windows XP).
On CPAN, there are a few more choices available:
I'm not precisely sure how JBrowseEntry currently compares to BrowseEntry, but at one time JBrowseEntry provided key bindings where JComboBox did not, and since it was an enhanced BrowseEntry, someone could replace any instances of BrowseEntry without breaking their existing code, and then take advantage of the enhancements, which is a real advantage for someone looking for a nice upgrade with little to no integration work. The same can <i>not</i> be said for JComboBox.It was never intended as a clone or enhanced BrowseEntry.
JBrowseEntry's document isn't that current unfortunately. It leads one to believe that JComboBox does not provide key bindings. At one time, this was true, but as of release 1.0, JComboBox also has key bindings and is generally more configurable than JBrowseEntry, and provides more out-of-the-box functionality. To be fair, this does come at price: JComboBox has a larger number of options and methods, and can be more difficult to learn. The hopeful payoff is that less time should be required to implement common Combo Box behavior leaving more time to implement core business requirements.
This document covers the 1.14 release of JComboBox.
Rob Seegel (RobSeegel@comcast.net)
Tk::JComboBox - Create and manipulate JComboBox widgets |