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

Hi
I am using 2 option menus in a program.
One menu gets it's variables from a unix "ls" command and
the other menu should be updated according to the
selected directory in the first option menu.
I used the following code, but it doesn't seem to work:
$mw->Label(-text=>"level1 ")->grid( $mw->Optionmenu(-textvariable=>\$selectedDir, -command=> sub{ @files=`ls $path/$selectedDir`; foreach (@files) {chomp();} }, -options=>\@myArr), $mw->Label(-text=>"level2 "), $mw->Optionmenu(-textvariable=>\$myFile, -options=>\@files) );
When the window is displayed, the second option box is empty,
and when i try to select something from it, i get an error.
I tried giving the $files[0] a value, but it still wasn't
updated after selecting a different option on the first option menu.
I am using Tk and this is not a web-based program.
Could someone please help ? Thanks

Replies are listed 'Best First'.
Re: Updating one option menu by the value of another
by converter (Priest) on Apr 29, 2003 at 11:13 UTC

    You need to assign the widget references returned by the constructors to variables so that your first Optionmenu can invoke the second Optionmenu's configure() method to configure the -options attribute.

    Give this code a try and see if it works for you. You'll have to replace the list of directories assigned to @myArr with directory names that exist on your system.

    #!/usr/bin/perl use warnings; use strict; use Tk; use Tk::widgets qw( Label Optionmenu ); my $mw = tkinit; my $selectedDir; my @files; my $path = '.'; my @myArr = qw(foo bar); my $myFile; my ($Label1, $OptMenu1, $Label2, $OptMenu2); $Label2 = $mw->Label(-text => "level2 "); # no -options: we'll let $OptMenu1 configure -options $OptMenu2 = $mw->Optionmenu( -textvariable => \$myFile, ); $Label1 = $mw->Label(-text => "level1 "); $OptMenu1 = $mw->Optionmenu( -textvariable => \$selectedDir, # -command is invoked when the widget is # allocated and when a selection is made: -command => sub { # redirect the output of ls(1) to /dev/null unless # you want stderr output on the console @files = `ls $path/$selectedDir 2>/dev/null`; #foreach (@files) { chomp() } chomp @files; # chomp() take a LIST warn 'configure $OptMenu2'; # who needs a debugger? $OptMenu2->configure(-options => \@files); }, -options => \@myArr, ); $Label1->grid($OptMenu1, $Label2, $OptMenu2); MainLoop;

    Update:
    Minor speeling correction.

Re: Updating one option menu by the value of another
by Improv (Pilgrim) on Apr 29, 2003 at 10:59 UTC
    I believe the problem is that @files is not filled in at the time the menus are being built. What you'll need to do is find a way to hook menu selection on the first menu, and install a handler that reconfigures the second menu. Incidentally, you can probably rewrite your file handling code so that it doesn't call ls and so it will actually only find directories. Here's a one-liner illustrating how you might look only at directories:
    print join "\n", grep {-d $_} <*>;
Re: Updating one option menu by the value of another
by meirgold (Acolyte) on Apr 29, 2003 at 12:44 UTC
    Thanks a lot guys - your suggestion seems to work !
    :-)