http://www.perlmonks.org?node_id=990930

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

I am trying to develop a config file manager. I need, initially, to be able to read and display the current keyword=value records, edit the values, add new records and delete old records. All works fine except the delete because I don't know, at the time the delete button is pressed, the name of the particular widget to remove or the keyword to delete from my hash. My code looks like this but clearly won't work because "$_" is not static and has changed (become undefined) by the time I try to use the button.
sub cfgRuntime { if (!%runtime) { loadConfig(); } $workframe -> Label(-text=>"Folder Separator") -> grid(-row=>1, -c +olumn=>1, -rowspan=>2); $workframe -> Radiobutton(-text=>"Windows", -value=>"\\", -variabl +e=>\$runtime{'fsep'}) -> grid(-row=>1, -column=>2, -sticky=>"w"); $workframe -> Radiobutton(-text=>"Unix", -value=>"/", -variable=>\ +$runtime{'fsep'}) -> grid(-row=>2, -column=>2, -sticky=>"w"); $workframe -> Button(-text => "Save these values", -command=>[\&up +dGUIInput, "runtime", "save"]) -> grid(-row=>1, -column=>3, -sticky=>"e"); $workframe -> Button(-text => "Discard these values", -command=>[\ +&updGUIInput, "runtime", "discard"]) -> grid(-row=>2, -column=>3, -sticky=>"e"); $row = 3; for (keys %runtime) { if ($_ eq "fsep") {next} $workframe -> Label(-text=>$_) -> grid(-row=>$row, -column=>1) +; $workframe -> Entry(-width=>100, -textvariable=>\$runtime{$_}) + -> grid(-row=>$row, -column=>2); $workframe -> Button(-text=>"Delete entry", -command=> sub { delete $runtime{$_}; } ) -> grid(-row=>$row, -column=>3); $rowsin = $row; $row++; } $btnNew = $workframe -> Button(-text=>"New variable", -command=>\&newVar ) -> grid(-row=>$row, -column=>1, -sticky=>"w"); }

Replies are listed 'Best First'.
Re: Clearing anonymous Tk widgets
by Anonymous Monk on Aug 31, 2012 at 07:50 UTC
      Other parts of the config file are much more complex than keyword=value. I wasn't going to confuse my objective with all that stuff. My ultimate objective is to find a means of tracking and controlling something for which I have no means of predicting an identifier. If I can write something like
      my $name = $frm->.....Button(-command=> sub{delete $hash{$name};$name->destroy()};
      that's easy. It's not so easy if I don't know, in advance, how many lines like the above I need nor what to use for the variable name in each case.

        that's easy. It's not so easy if I don't know, in advance, how many lines like the above I need nor what to use for the variable name in each case.

        you don't need lines, you need a loop

        Tk::ObjScanner and Tk::WidgetDump use loops, you can use them too

Re: Clearing anonymous Tk widgets
by Anonymous Monk on Aug 31, 2012 at 07:52 UTC
    To properly closure you should write
    my $goner = $_; ... sub { delete $runtime{$goner} }
      I did consider that but I don't know the name of $goner in advance. There might be one line in the input file or there might be 50. So what I'm trying to achieve is a loop scanning all lines in the input file (they are loaded into a hash by XML::Simple) then building an entry in a Tk GUI window for each line. There are three columns: keyword (as a read only Label), value (r/w as an Entry) and a delete button. The delete button should do two things: remove the entry from the hash with key=keyword and remove (destroy?) the row in the GUI window.

        Play with this

        #!/usr/bin/perl -- use strict; use warnings; use Tk; use Tk::WidgetDump; use Tk::ObjScanner; my %ons; my $mw = tkinit(); for (1 .. 3) { my $goner = $_; $ons{$_} = $mw->Button( -text => "B $_", -command => sub { delete($ons{$goner})->destroy; ## this works, proper closu +re #~ delete($ons{$_})->destroy; ## this doesnt, $_ is alias } )->pack; } $mw->WidgetDump; ## before scan_object Tk::ObjScanner::scan_object( { mw => $mw, ons => \%ons } ); ## after W +idgetDump MainLoop();

        I did consider that but I don't know the name of $goner in advance.

        Yes you do, its $_, its the keys of %runtime -- if thats not the case, you'll have to restate your question