GrandFather has asked for the wisdom of the Perl Monks concerning the following question:

As often happens when preparing a SoPW this question was answered while stripping the code down to the "bare essentials". However the issue was subtle enough that I decided to post it here anyway so others might benefit.

The sample code below creates a dialog box containing a JComboBox widget. The intent is to use it to select a person from a list who's details are to be edited in the dialog. I wanted to set the initialy selected entry to either a value passed into the edit code, or to the first entry. The code as given fails to do that, although it looks like it ought to.

Note that $id is set to the desired value when it is declared and that the contents of $id are used to set the selected item using $IDText->setSelected ($id);.

use strict; use warnings; use Tk; use Tk::DialogBox; use Tk::JComboBox; my $main = MainWindow->new (-title => "Test JComboBox"); EditPlayers ($main); sub EditPlayers { my ($main, $sel) = @_; my @ids = qw(Fred Joe Bob); my $dlg = $main->DialogBox (-title => "Member Information", -butto +ns => ["OK", "Cancel"]); my $id = $sel || (@ids && $ids[0]) || ''; my $IDText = $dlg->add ( 'JComboBox', -mode => 'readonly', -selectcommand => [\&changeEditPlayer, \$id], -validate => 'match', -textvariable => \$id, ); $IDText->form (-left => '%0', -right => '%100', -top => '%0'); $IDText->configure (-options => \@ids); $IDText->setSelected ($id); return if $dlg->Show (-global) ne 'OK'; } sub changeEditPlayer { my ($id, $widget, $index, $value, $name) = @_; return 1 if ! defined $name; print "$name\n"; }

However when the dialog opens no value is selected and the diagnostic print in the selectcommand handler doesn't fire.

It turns out that with $id bound to the widget (-textvariable => \$id,), when the list items are set ($IDText->configure (-options => \@ids);) $id is set to undef. The fix is to use the code that was used to initialise $id in place of $id where the selection is set: $IDText->setSelected ($sel || (@ids && $ids[0]) || '');.


DWIM is Perl's answer to Gödel

Replies are listed 'Best First'.
Re: How do I set the default item in a Tk::JComboBox
by zentara (Cardinal) on Jun 17, 2006 at 11:05 UTC
    Hi, nice example. Maybe this is a stupid observation, but the original code works if I put the -options into the dialog add statement. Maybe there is a good reason why you put them into a separate configure? I'm guessing that the problem comes from the -textvariable reference not detecting the change to \$id.
    my $id = $sel || (@ids && $ids[0]) || ''; my $IDText = $dlg->add ( 'JComboBox', -options => \@ids, -mode => 'readonly', -selectcommand => [\&changeEditPlayer, \$id], -validate => 'match', -textvariable => \$id, ); # $IDText->configure (-options => \@ids); $IDText->setSelected ($id); return if $dlg->Show (-global) ne 'OK'; }

    Another way I sometimes use, is to set the -textvariable directly to the first array element. This works, but I really havn't tested it, for glitches. :-)

    #!/usr/bin/perl use strict; use warnings; use Tk; use Tk::DialogBox; use Tk::JComboBox; my $main = MainWindow->new (-title => "Test JComboBox"); EditPlayers ($main); sub EditPlayers { my ($main, $sel) = @_; my @ids = qw(Fred Joe Bob); my $dlg = $main->DialogBox (-title => "Member Information", -butto +ns => ["OK", "Cancel"]); my $IDText = $dlg->add ( 'JComboBox', -options => \@ids, -mode => 'readonly', -selectcommand => [\&changeEditPlayer, \$ids[0]], -validate => 'match', -textvariable => \$ids[0], ); $IDText->form (-left => '%0', -right => '%100', -top => '%0'); # $IDText->setSelected ($ids[1]); #works return if $dlg->Show (-global) ne 'OK'; } sub changeEditPlayer { my ($id, $widget, $index, $value, $name) = @_; return 1 if ! defined $name; print "$name\n"; }

    I'm not really a human, but I play one on earth. flash japh

      If I put the -options = \@ids, in the add then changeEditPlayer fires with $name set to "index: 0" (or other appropriate index number if a selected value is supplied). When a selection is made by the user, or if the list is hooked up outside the add, the text for the selected element is provided in $name as expected.

      A bug in the widget code maybe? Anyway the code evolved into that form as a result rather than adding special case code to changeEditPlayer to deal with the problem.


      DWIM is Perl's answer to Gödel