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

I looked for an answer to this before posting, but I am not sure exactly what it is called that I am trying to do. I am writting a program using Tk. I would like to pass some of the Tk functions to packaged subroutines in a seperate .pm file, rather than putting everything in my main program. I am having a hard time passing a widget that was created in the main program into the .pm package. In the following code example, I would like to take the "subbie_1" subroutine and place it in a seperate .pm file. (I know I have to add all the handeling in the beginning I.E. require Exporter, etc). I just wanted to give an example of my problem.
use Tk; # Main Window my $mw = new MainWindow; #GUI Building Area my $frm_name = $mw -> Frame()->pack(); my $lab = $frm_name -> Label(-text=>"Name:")->pack(-side=>'left'); my $ent = $frm_name -> Entry(-textvariable=>\$entry_var)->pack(); $ent->bind('<Return>'=> \&subbie_1); #Text Area my $textarea = $mw -> Frame()->pack(); my $txt = $textarea -> Text(-width=>40, -height=>10)->pack(); MainLoop(); sub subbie_1 { $txt->insert('end', "$entry_var\n"); }
How do I pass the $txt widget into a subroutine that is outside of the main program (seperate .pm file) so that I can call $txt->insert? My knowledge of Perl is still novice, so please be nice in responding. I have set up subroutines in the past, with little or no problem. However, I can't seem to get it to work with Tk. Thoughts?

Replies are listed 'Best First'.
Re: Newbie TK question
by liverpole (Monsignor) on Jun 07, 2006 at 15:22 UTC
    Hi hebes_99,

    That's a very good question, actually.

    Here's one straightforward way to do it, assuming you have a package called my_functions, and you want to call my_functions::subbie_1:

    $ent->bind('<Return>'=> sub { my_functions::subbie_1() });

    What the above code does is to create an anonymous (ie. unnamed) subroutine, which is a pointer to a subroutine that gets invoked whenever the Return key is struck.

    You can also call subbie_1 with arguments if need be, of course.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      Beautiful...that worked perfectly..... That is a very straightforward way, and actually makes sense once I see it. Thanks much!!!!!!!!!!!
Re: Newbie TK question
by GrandFather (Saint) on Jun 07, 2006 at 18:50 UTC

    liverpole's technique is well worth knowing about, but is not the only way of achieving what you want with Tk's bind. Note the array ref passed in place of the subroutine ref in the bind here:

    use strict; use warnings; use Tk; sub subbie_1 { my ($widget, $txt, $entry_var) = @_; $txt->insert('end', "$$entry_var\n"); } # Main Window my $mw = new MainWindow; my $entry_var = 'Some text'; #GUI Building Area my $frm_name = $mw -> Frame()->pack(); my $lab = $frm_name -> Label(-text=>"Name:")->pack(-side=>'left'); my $ent = $frm_name -> Entry(-textvariable=>\$entry_var)->pack(); #Text Area my $textarea = $mw -> Frame()->pack(); my $txt = $textarea -> Text(-width=>40, -height=>10)->pack(); $ent->bind('<Return>' => [\&subbie_1, $txt, \$entry_var]); MainLoop();

    Update: note that because subbie_1 gets the widget ($ent in this case) there is no need to pass $entry_var so the following modified lines can be used:

    ... sub subbie_1 { my ($widget, $txt) = @_; $txt->insert('end', $widget->get () . "\n"); } ... $ent->bind('<Return>' => [\&subbie_1, $txt]); MainLoop();

    In fact you may not need $entry_var at all now.


    DWIM is Perl's answer to Gödel
      OK...that worked great for the entry bind. Now, how would I add text without using bind? In other words, I just want to put some sort of text in (not dependent on the user entering test and not using bind). Does that make sense?

        Sorry for the long delay before replying. This is possibly what you want:

        use strict; use warnings; use Tk; # Main Window my $mw = new MainWindow; #GUI Building Area my $frm_name = $mw -> Frame()->pack(); my $lab = $frm_name -> Label(-text=>"Name:")->pack(-side=>'left'); my $ent = $frm_name -> Entry(-text=>'Some text')->pack(); #Text Area my $textarea = $mw -> Frame()->pack(); my $txt = $textarea -> Text(-width=>40, -height=>10)->pack(); MainLoop();

        DWIM is Perl's answer to Gödel