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

I am working on an app for win NT4 with Tk with plans to export it with perl2exe. I have mulitiple windows that I would like to close with a exit button. I was thinking one sub with a var would be the shortest way of writting the code. (ex:
sub close_win(var) { var->destory; } button(-command=>\&close_win($thiswindow))->pack...
...) I can't seem to find how to write a function and pass a variable. Any suggestions on where to find the proper way of writting a function?

edited by ybiC: s/pre/code as per Monastery convention for example code

Replies are listed 'Best First'.
Re: Functions and Tk
by bobn (Chaplain) on Aug 24, 2003 at 01:30 UTC

    Here's an example that works:

    #!/usr/bin/perl -w use Tk; my $mw = MainWindow->new(-title=>"Demo"); my $HlpBttn = $mw->Button(-text=>"Make NEW Window", -command=> sub { m +ake_win(); }); $HlpBttn->pack(-padx =>60, -pady =>10); MainLoop; sub make_win { my $win = $mw->Toplevel(-title=>'new window'); my $Bttn = $win->Button(-text=>"CLOSE this window", -command=> sub { close_win($win); } )->pack(-padx =>60, -pady =>10); } sub close_win { my $thiswin = $_[0]; $thiswin->destroy; }

    make_win creates a closure in the -command option, creating an anonymous subref that carries around with it an instance of $win. When the "CLOSE this window" button is pressed in a given window, the coderef that is exectuted uses the instance of $win that it carries with it.

    Actually, I could have just said $win->Button(yada-yada...-command=> sub { $win->destroy })....

    Note that for either way to work, $win must be a lexical, outside the scope of the anonymous coderef.

    --Bob Niederman, http://bob-n.com

    All code given here is UNTESTED unless otherwise stated.

      *yuck* That is a pretty obfuscated way of going about it -- Tk::callbacks
      #!/usr/bin/perl -w use Tk; my $mw = MainWindow->new(-title=>"Demo"); my $HlpBttn = $mw->Button( -text =>"Make NEW Window", -command => [ \&makeWindow, $mw ], # calls makeWindow and passes +$mw as the first argument ); $HlpBttn->pack(-padx =>60, -pady =>10); MainLoop; sub makeWindow { my $parent = shift; my $win = $parent->Toplevel(-title=>'new window'); my $Bttn = $win->Button( -text=>"CLOSE this window", -command=> [ 'destroy', $win ], # calls destroy on $win )->pack( -padx =>60, -pady =>10, ); } __END__
      Sure closures aren't that obfuscated, but makeWindow needn't be tied to $mw (need not be a closure), and the "CLOSE this window" command need not be a closure either.

      MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
      I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
      ** The third rule of perl club is a statement of fact: pod is sexy.

      I changed my code to match yours. There is still something wrong. I am getting the error.
      Tk::Error AUTOLOAD 'Tk::Toplevel::destory' at line 97 Carp::croak at C:/usr/lib/Carp.pm line 191 Tk::Widget::__ANON__ at C:/usr/lib/Tk/Widget.pm line 338 main::Exit_Win at line 97 main::__ANON at line 82 [\&main::__ANON__ at line 82 Tk callback for .toplevel.frame2.button1 Tk::__ANON__ at C:/usr/lib/Tk.pm line 228 Tk::Button::butUp at C:/usr/lib/Tk/Button.pm line 111 [command bound to event]
      $win->Button(...-command=> sub {$win->destory} )... Works great, but I would like to have the sub work.

        It isn't really working. Tk::Error AUTOLOAD 'Tk::Toplevel::destory' at line 97 happend because you said ->destory when you meant ->destroy - and your window fgoes away because your program died.

        To make the subroutine work, I think the part you're missing is this:

        doit('here is my input', 'some more'); sub doit { my ( $in1, $in2 ) = @_; print "$in1\n"; print "$in2\n"; }

        subs all receive their parameters in @_ - then you transfer them in to local variables for readability, isolation, etc.

        In the orginal form of my example the line my $thiswin = $_[0]; in the close_win sub did this, just getting the first (and only) elment of @_;

        --Bob Niederman, http://bob-n.com

        All code given here is UNTESTED unless otherwise stated.

        The answer is right in front of you: you misspelled destroy.

        converter

      thanks for your help. passing vars to subs is something I haven't seemed to find yet. perldoc perlsub, if it says so, doesn't make it clear to a newbie.
      Thanks again, James