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

'lo everyone... I've been continuing my explorations with Perl/Tk and I'm close to completing my first (small) Perl/Tk project.

However I'm having troubles with callbacks now. I've not used them in my perl very much and the following code shows an example of what I'm trying to do:

use Tk; use Tk::JComboBox; my $mw = MainWindow->new(); my $jcb = $mw->JComboBox( -relief => 'sunken', -mode => 'editable', -listbackground => 'white', -popuprelief => 'groove', -highlightthickness => 0, -choices => [qw/Black Blue Green Purple Red Yellow/] )->pack; $mw->Button( -text => 'func', -command => [ \&test, $jcb->getSelectedValue($jcb->getSelectedIndex()) ], # -command => [ \&test, 2 ], )->pack; $mw->Button( -text => 'embed', -command => [ sub { my ($p1); printf("e: \$p1 = >>$p1<<\n"); }, $jcb->getSelectedIndex() ] )->pack; MainLoop; sub test { my ($p1) = @_; printf("f: \$p1 = >$p1<\n"); }
I'm expecting to get the integer that JComboBox->getSelectedIndex() returns passed into the sub and that is, indeed what happens when I use a number but the result of the method call isn't being passed.

I've looked through this site but haven't been able to find anything that talks about the getSelectedIndex() method and what it returns. The docs. for JComboBox just talk about returning an index and not how to pass that value elsewhere.

Apologies for the basic question... but my experiments and research have hit a brick wall!

Many thanks for any forthcoming suggestions.

John

Replies are listed 'Best First'.
Re: Is the problem JComboBox, Perl/Tk or (probably) me!?
by eserte (Deacon) on May 14, 2004 at 13:03 UTC
    You can't use the [ ... ] styled callbacks in this case, because all parameters are evaluated while the buttons are created, which is too early. Rather use normal anon subs for the callbacks:
    -command=>sub {test($jcb->getSelectedValue($jcb->getSelectedIndex())}
Re: Is the problem JComboBox, Perl/Tk or (probably) me!?
by Joost (Canon) on May 14, 2004 at 13:14 UTC
    You are not assigning a value to $p1 in the second button, and you're not passing an argument to &test in the first button. Forgot about the [ .. ] construct in Tk, see above for actual problem. this is why i always use sub { ... } callbacks in Tk, though.

    I think you want

    $mw->Button( -text => 'func', -command => sub { test($jcb->getSelectedValue($jcb->getSelectedInde +x())) } , )->pack; $mw->Button( -text => 'embed', -command => sub { my $p1 = $jcb->getSelectedIndex(); printf("e: \$p +1 = >>$p1<<\n"); } )->pack;

Re: Is the problem JComboBox, Perl/Tk or (probably) me!?
by ozboomer (Friar) on May 14, 2004 at 13:29 UTC
    Ok... So it seems there is something about the (square brackets) construct that says, 'at widget creation time', whereas the sub {} construct says, 'at widget activation time'. Very much a trick for young players, eh?

    I'll see if I can find some more explanations about this. I assume it's mentioned somewhere in 'Mastering Perl/Tk'?

    Thanks for your help, folks.

    John

      Yeah, that square-bracket suroutine syntax is one of the trickiest aspects of Tk. Here are a couple of other examples which demonstrate things to watch out for(gleamed from usenet, probably written by Ala Qumsieh, a Tk guru). The details are in "perldoc Tk::callbacks" , but that is hard to get without examples.
      #!/usr/bin/perl -w use Tk; my $xx=99; sub a{ my $x=$_[0]; my $wm= new MainWindow; my $l=$wm->Entry(-textvariable => \$x)->pack(); $wm->Button(-text => "Apply", # -command => [ \&onApply, "$x"])->pack(); -command => [ \&onApply, \$x])->pack(); } # Here, you specify an anonymous list as the value of the -command opt +ion, # which is a legal callback syntax. The problem is that this list will + be # created when the button is created, and the first element in the lis +t is # the reference to onApply(), but the second element is the *value* of + $x # at the time the list is created, which is the initial value of $x. T +he # variable $x itself has nothing to do with it anymore, so changing it + # will not change this anonymous list. # What you can do is pass a reference to $x instead: # -command => [\&onApply, \$x], # and change your onApply() sub to reflect that. sub onApply{ # my $z=$_[0]; my $z = ${$_[0]}; print "XX=$z\n"; }; &a($xx); MainLoop();
      AND##########################################
      #!/usr/bin/perl #for example the following is wrong my $row = 0; my $column = 0; for (my $i = 9; $i >= 0; $i--) { $button{$i} = $mw->Button(-text => "$i", -width => '3', -height => '1', -command => &numpress($i)) ->grid(-row => $row, -column => $column); $column++; if($column > 2){$column = 0; $row++;} } MainLoop; ####################################################### # Now the problem is here: -command => &numpress($i)) # The thing being assigned to the "-command" attribute needs # to be an anonymous subroutine, a reference to a named subroutine, # or else a reference to an array whose elements are: # named_subroutine_ref, arg1(, arg2 ...) -- in other words, # either of the following would be the right way to do what you want: -command => sub { numpress( $i ) } # or -command => [ \&numpress, $i ] #The way you had it written, your subroutine is actually being called + #when the Button is being created, and Perl/Tk is trying to use the #return value of the sub as the value for "-command" -- not good.

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