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

Hi Perl Monks, I'm trying to create a GUI which consists of several BrowseEntries and stores the Index and the Value of every Selection for further use. I'm doing this via the -browsecmd Option. But since there will be a lot of BrowseEntries and I don't want to write as many Subroutines I want to store the BrowseEntries in a Hash and just pass their key to a single Subroutine like in the code below:

#!usr/bin/perl use strict; use warnings; use Tk; use Tk::BrowseEntry; my $mw = MainWindow->new(); my %entries; my %entries_list; #Definition of Browseentry 1 ############### $entries{option1} = $mw->BrowseEntry( -browsecmd=>\&selection("option1") )->pack(); $entries_list{option1} = $entries{option1}->Subwidget("slistbox"); for (qw/Word1 Word2 Word3 Word4/) { $entries{option1}->insert("end", $_); } #Definition of Browseentry 2 ############### $entries{option2} = $mw->BrowseEntry( -browsecmd=>\&selection("option2") )->pack(); $entries_list{option2} = $entries{option2}->Subwidget("slistbox"); for (qw/Word5 Word6 Word7 Word8/) { $entries{option2}->insert("end", $_); } ########################################### $mw->MainLoop(); exit 0; ########################################### sub selection { print "Index: ".$entries_list{$_[0]}->curselection ." Value: ".$entries_list{$_[0]}->get( $entries_list{$_[0]}->curselection() )."\n"; #<-this is where the errormessage points } #selection

The Problem is, that -browsecmd calls the selection Subroutine upon loading the GUI when i pass a Parameter and i get:
"Can't call method "curselection" on an undefined value at code_snippet.pl line 29."
Makes sense since there is no Subwidget defined when selection is called. It does work though if i don't pass a Parameter, but then i can't use a single Subroutine for every BrowseEntry.

I tried adding  return if ! defined $entries_list{$_[0]}; to the Subroutine but that leads to the following errormessage
Tk::Error: Odd number of args to Tk::BrowseEntry->new(...)
Tk callback for .
Tk::Widget::new at /usr/lib64/perl5/vendor_perl/Tk/Widget.pm line 164
Tk::Widget::__ANON__ at /usr/lib64/perl5/vendor_perl/Tk/Widget.pm line 256
Odd number of args to Tk::BrowseEntry->new(...)
at code_snippet.pl line 15

Any advice is highly welcomed. ;)

Replies are listed 'Best First'.
Re: Tk::Browseentry -browsecmd Option with Subroutine Parameter
by choroba (Cardinal) on Mar 19, 2015 at 12:15 UTC
    Here's the problem:
    \&selection("option1")

    This is not a reference to subroutine called with a parameter. In fact, there's no such a thing as a code reference plus parameters. You have two options:

    1. Use a subroutine:
      -browsecmd => sub { selection('option1') }
    2. Tk allows you to specify a callback as an array reference (the first member is the code ref, the rest the parameters):
      -browsercmd => [ \&selection, 'option1' ]
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      That absolutely solves my problem! Thank you!
      Another example of: "Once you do it right, it works" ;)

Re: Tk::Browseentry -browsecmd Option with Subroutine Parameter
by Anonymous Monk on Mar 19, 2015 at 10:54 UTC

    Any advice is highly welcomed. ;)

    use more newlines when formatting your code

    I'll be back with more advice

      True. I tried to make the code somewhat more comfortable to read, but i can't help with the print-Statement.
Re: Tk::Browseentry -browsecmd Option with Subroutine Parameter
by Anonymous Monk on Mar 19, 2015 at 11:00 UTC

      Actually, I was able to find a workaround based on the code from the Link. Since my Values are unique, it is possible to identify the Browseentry and the Index when the Value is passed along to the Subroutine. But choroba provided a more direct way to solve my problem.