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

Fellow monks,

I'm working on a Tk app that uses the ListBox method in Tk to return results from a search. All well and good until it goes out of scope in the subroutine that sets it up.

What I am trying to do, without success up to this point, is to create a reference to this method so that I don't have a huge subroutine that both defines the list box and takes care of it's processing.

I've tried to set up my list box with a reference as:

# snippet of a subroutine that defines the widget layout my $res; { my $results = $search_frame->Listbox( -background => "white", -relief => "sunken", -borderwidth => 2, -width => 20, -height => 12, ) ->place( -in => $search_frame, -x => 20, -y => 175); $res = \$results; }

but I keep getting the message that $ref isn't defined when I try to access it later in the program by

$res->insert('end', $list[$_]->{last});

I'm assuming, and perhaps incorrectly, that when I move out of the sub that defines the listbox, I'm losing scope. But if I have to move the $ref outside as a global, doesn't that sort of defeat the purpose of defining it as a reference to the ListBox method?

I've been banging my head for a few days on this now, so any help would be greatly appreciated!

There is no emoticon for what I'm feeling now.

Replies are listed 'Best First'.
Re: Calling a TK Method by reference
by Joost (Canon) on Jul 09, 2004 at 08:12 UTC
    But if I have to move the $ref outside as a global, doesn't that sort of defeat the purpose of defining it as a reference to the ListBox method?
    Well... there's not really a point in making it a reference, as a ListBox is already an object (and so, a reference too) so you should be able to copy it (as I showed in the post above).

    And if you don't want to make $listbox global, make it a lexical in a slightly higher scope:

    # main code here... { my $listbox; sub sub_that_makes_listbox { .. }; sub sub_that_alters_listbox { .. }; }
    You could also return $listbox from the first sub, and then pass it to the second. Or store $listbox in an object, or create a new closure in sub_that_makes_listbox... I tend to use all four options. Use whatever you're comfortable with.

    Anyway, try looking at perlreftut and perlref for more information about references and closures.

Re: Calling a TK Method by reference
by Joost (Canon) on Jul 09, 2004 at 08:02 UTC
      I don't think this is true --- every Tk geometry manager returns the widget reference so one can write
      $widget = $parent->Widget->pack(...); $widget = $parent->Widget->grid(...); $widget = $parent->Widget->place(...);
        update: The docs are wrong.

        I did not expect it either, and I haven't tested it, but this is from Tk::place (emphasis mine):

        $slave->place?(-option=>value?, -option=>value, ...?)? The place method arranges for the placer to manage the geometry of $slave. The remaining arguments consist of one or more -option=>value pairs that specify the way in which $slave's geome- try is managed. If the placer is already managing $slave, then the -option=>value pairs modify the configuration for $slave. The place method returns an empty string as result.
Re: Calling a TK Method by reference
by eserte (Deacon) on Jul 09, 2004 at 09:15 UTC
    $res = \$results;

    Now you have a reference to a listbox reference. To use this one, you have to dereference $res again:

    $$res->method(...)

    But as joost already said, it's not needed to use the extra reference here.