Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Re^2: Clearing anonymous Tk widgets

by murrayn (Acolyte)
on Aug 31, 2012 at 10:03 UTC ( #990966=note: print w/replies, xml ) Need Help??

in reply to Re: Clearing anonymous Tk widgets
in thread Clearing anonymous Tk widgets

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.

Replies are listed 'Best First'.
Re^3: Clearing anonymous Tk widgets
by Anonymous Monk on Aug 31, 2012 at 10:51 UTC

    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();
      That looks promising. I'll have a play over the next few days (it's Father's Day in Aus tomorrow - there'd be trouble if I was messing with Perl code then!). I was starting to think I'd need an array of Tk Frames and go destroying them but this looks more elegant. Thanks. I'll let you know how it goes.
        So this is my rewrite of the above using a hash to track each entry which I may want to delete...
        for (keys %runtime) { $widgetname = $_; $widgetrow{$widgetname} = $workframe -> Frame(); $wrLabel{$widgetname} = $widgetrow{$widgetname} -> Label(-text=>$w +idgetname) -> grid(-row=>1, -column=>1); $wrEntry{$widgetname} = $widgetrow{$widgetname} -> Entry(-width=>1 +00, -textvariable=>\$runtime{$widgetname}) -> grid(-row=>1, -column=> +2); $wrButton{$widgetname} = $widgetrow{$widgetname} -> Button(-text=> +"Delete \"$widgetname\" entry", -command=>sub { my $deltgt = $widgetname; print "Deleting \"$deltgt->$runtime{$deltgt}\"\n"; delete $runtime{$deltgt}; print "Hash entry deleted\n"; delete($wrLabel{$deltgt})->destroy(); print "Widget label deleted and destroyed\n"; delete($wrEntry{$deltgt})->destroy(); print "Widget entry deleted and destroyed\n"; delete($wrButton{$deltgt})->destroy(); print "Widget button deleted and destroyed\n"; $widgetrow{$deltgt} -> destroy(); print "Widget row destroyed\n"; } ) -> grid(-row=>1, -column=>3); $widgetrow{$widgetname} -> grid(-row=>$row, -column=>1, -columnspa +n=>3); $rowsin = $row; $row++; }
        This produces a Tk frame for each variable and puts three objects in that frame: 1) the variable name, as a Tk Label, which is the key to the %runtime hash, 2) the value from the %runtime hash as a Tk Entry field and 3) a Tk Button with text saying "Delete "Variable" Entry".

        After that frame is built, it's inserted in $workframe on the next available line.

        This all works nicely and the buttons all have their correct variable names written on them.

        However, when I press the button, ANY button, the value of $widgetname is the last key accessed from the %runtime hash and that's the entry which is deleted from the hash and the subframe which is deleted from the workframe. A subsequent attempt to use any button generates an Tk error stating that I cannot delete an undefined object.

        (I put the "my $deltgt=$widgetname" line in hoping that I might sufficiently localise the variable at "build" time that I could retain it ready for execution time - didn't work, not surprised.)

        Perhaps I need a mechanism to read the text from the button which invoked the subroutine. The button is generated and remains static as the loop rolls on so the target variable name can be stored therein if only I could extract that.

Re^3: Clearing anonymous Tk widgets
by Anonymous Monk on Aug 31, 2012 at 10:34 UTC

    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

      Unless I've done something silly (highly plausible explanation!), I'm not seeing evidence to support that theory. $_ is the value of the key when I build the line in the GUI window and it displays exactly as I'd expect it to and when I put a button on the line saying delete $runtime{$_} it works the first time then objects the second time (makes sense too - the delete worked, so there's nothing there now). So now I want to remove the line from the GUI and I don't have a Tk widget name to destroy.

        Unless I've done something silly (highly plausible explanation!) ... So now I want to remove the line from the GUI and I don't have a Tk widget name to destroy

        What line from what GUI?

        See Re^3: Clearing anonymous Tk widgets and make sense :)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://990966]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2016-12-11 06:49 GMT
Find Nodes?
    Voting Booth?
    On a regular basis, I'm most likely to spy upon:

    Results (168 votes). Check out past polls.