Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

failed AUTOLOAD widgets when trying to destory widget

by reaper9187 (Scribe)
on Oct 26, 2012 at 07:35 UTC ( #1001015=perlquestion: print w/ replies, xml ) Need Help??
reaper9187 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,
I need some help with a GUI application i have been trying to build lately. One of the major problems i'm facings is when i try to close the Top level widget by destroying it(see code) and try to reload it later, the widget don't auto load and gives me the error

Tk::Error: Failed to AUTOLOAD 'Tk::Widget::insert' at C:/Dwimperl/perl +/site/lib/ Tk/Derived.pm line 469 Carp::croak at C:/Dwimperl/perl/lib/Carp.pm line 100 Tk::Widget::__ANON__ at C:/Dwimperl/perl/site/lib/Tk/Widget.pm line 3 +47 Tk::Derived::Delegate at C:/Dwimperl/perl/site/lib/Tk/Derived.pm line + 469 Tk::Widget::__ANON__ at C:/Dwimperl/perl/site/lib/Tk/Widget.pm line 3 +22 main::push_button2 at top.pl line 62 Tk callback for .toplevel.button1 Tk::__ANON__ at C:/Dwimperl/perl/site/lib/Tk.pm line 251 Tk::Button::butUp at C:/Dwimperl/perl/site/lib/Tk/Button.pm line 175 <ButtonRelease-1> (command bound to event)

Please help..!! Below is the code:
#!/usr/local/bin/perl use Tk; require Tk::ROText; require Tk::TextUndo; use Carp; use Tk::widgets qw(Canvas); use Tk::Xlib; use Math::Cartesian::Product; use List::Util qw[min max]; use List::MoreUtils qw(firstidx); # Main Window my $mw = new MainWindow; $mw->title('File preview'); $mw->scaling($ARGV[0]) if (@ARGV); my $screen = $mw->Screen; my $width1 = $screen->WidthOfScreen; my $height1 = $screen->HeightOfScreen; $mw->Frame(-background => 'red')->pack(-ipadx =>50, -side => "left", - +fill => "y",); #Making a text area my $txt = $mw -> Scrolled('ROText',-width => $width1, height => $heigh +t1, -scrollbars=>'e', -font => "fixed 10 bold") -> pack (); $txt->insert('end', ""); #Declare that there is a menu my $mbar = $mw -> Menu(); $mw -> configure(-menu => $mbar); #The Main Buttons my $file = $mbar -> cascade(-label=>"File ", -underline=>0, -tearof +f => 0); my $tool= $mbar -> cascade(-label =>"Tools ", -underline=>0, -tearo +ff => 0); my $parser = $mbar -> cascade(-label =>"Check ", -underline=>0, -te +aroff => 0); my $help = $mbar -> cascade(-label =>"Help ", -underline=>0, -tearo +ff => 0); ## Tools Menu ## $tool -> command(-label => "ABC", -underline=>0, -command=> \&nwplan ); $tool -> command(-label => "CC", -underline=>0, -command=> \&optimize ); $tool -> separator(); $tool -> command(-label =>"WW", -underline =>1, -command => \&do_top); $tool -> command(-label =>"Clear", -underline => 0, -command => sub {$txt->delete('1.0','end');}); MainLoop; sub do_top { if (! Exists($tl)) { $tl = $mw->Toplevel; $tl->title('Help'); $tl->geometry( "1000x700" ); my $frame = $tl->Frame()->pack; my $lab = $tl->Label()->pack; my $ent = $tl->Entry()->pack; $tl->Button(-text => 'Exit',-command => sub { $tl->destroy;})->pa +ck; $tl->Button(-text => 'Open File1',-command =>\&push_button2)->pack; my $text = $tl->Scrolled('Text')->pack(); sub push_button2{ $text->insert('end',"You pushed button2\n");} } else { $tl->deiconify; $tl->raise; } }

Comment on failed AUTOLOAD widgets when trying to destory widget
Select or Download Code
Re: failed AUTOLOAD widgets when trying to destory widget
by Anonymous Monk on Oct 26, 2012 at 08:22 UTC

    If you had  use strict; use warnings: you would have been warned

    Variable "$text" will not stay shared at file line 1

    If you had used diagnostics you'd have gotten

    (W closure) An inner (nested) named subroutine is referencing a lexical variable defined in an outer named subroutine. When the inner subroutine is called, it will see the value of the outer subroutine's variable as it was before and during the *first +* call to the outer subroutine; in this case, after the first call to th +e outer subroutine is complete, the inner and outer subroutines will no longer share a common value for the variable. In other words, the variable will no longer be shared. This problem can usually be solved by making the inner subroutine anonymous, using the sub {} syntax. When inner anonymous subs that reference variables in outer subroutines are created, they are automatically rebound to the current values of such variables.

    Read Tutorials: Closure on Closures, Lexical scoping like a fox

    If you're going to use named subs, use pre-declare any my variables (like $tl and $text ) in the largest possible scope (before any sub definitions) or simply use our globals, and you'll be fine with strict/warnings, and you'll avoid calling methods on destroyed object ( you'll avoid Failed to AUTOLOAD... )

    Or , keep what you have, but use anonymous sub/anonymous closure

    sub do_top { if ( !Exists($tl) ) { $tl = $mw->Toplevel; $tl->title('Help'); $tl->geometry("1000x700"); my $frame = $tl->Frame()->pack; my $lab = $tl->Label()->pack; my $ent = $tl->Entry()->pack; #### ANONYMOUS SUB , ANONYMOUS CLOSURE, #### CLOSED OVER LEXICAL $text #### $text is lexical to if {} block in do_top my $text = $tl->Scrolled('Text'); my $push_button2 = sub { $text->insert( 'end', "You pushed button2\n" ); }; $tl->Button( -text => 'Exit', -command => sub { $tl->destroy; +} )->pack; $tl->Button( -text => 'Open File1', -command => $push_button2 + )->pack; $text->pack(); } else { $tl->deiconify; $tl->raise; } }
      Thank you so much .!!!!
Re: failed AUTOLOAD widgets when trying to destory widget
by zentara (Archbishop) on Oct 26, 2012 at 11:37 UTC
    I recognize that reusable toplevel code. When I run your code, all I needed to do was ( in addition to use warnings; use strict; ) was to add a global my $tl

    Then the code runs fine, with a warning that on subsequent invoking of the reusable toplevel $tl, the Text widget from the last invocation will be gone.

    So just add a global my $tl;

    The whole idea of the reusable toplevel was to prevent memory gains, and this code may be such a beast. Everytime you run the toplevel, the private Text widget it contained gets stuffed aside into no-man's land, where memory accumulates. The Text widget I included with that toplevel example, is not needed. If you do need a persistent Text widget, for that reusable toplevel, just make my $text; a global variable, rather than just scoped to the toplevel subroutine.


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      pardon the stupid question, but how do you invoke the grid manager for top level windows, I've been tryin to do it like this:
      my $frame = $tl->Frame()->pack; my $lab = $tl->Label()->pack; my $ent = $tl->Entry()->pack; my $label = $frame -> Label(-text=>"NQR Reports "); $lab -> grid(-row=>0,-column=>0); $ent -> grid(-row=>0,-column=>1); $label -> grid(-row=>0,-column=>0); $frame -> grid(-row=>2,-column=>1,-columnspan=>2); my $but1 = $tl->Button( -text => 'Open File1', -command => $push_butt +on2 )->pack; $but1 -> grid(-row=>2,-column=>2,-columnspan=>2);

      The code starts executing but the top level window is never created and the system jus hangs .. Any suggestions ??
        As far as I know, you can't mix pack and grid. First you pack() your widgets, then you try to use grid() on them, you can't. See Geometry Management

        Here is a simple grid usage:

        #!/usr/bin/perl use warnings; use strict; use Tk; use Data::Dumper; my $top = new MainWindow(); #my %items = ( A => [1,1a], B => [2,2a], C => [3,3a] ); my $count = 0; my %items = (); for('A'..'Z','a'..'z'){ $count++; $items{$_} = [$count, "$count-a"]; } my $row = 0; foreach my $item ( sort keys(%items) ) { #print @{$items{$item}},"\n"; $top->Label( -text => $item, -anchor => "w", -relief => 'solid', #will show gridlines )->grid( -row => $row, -column => 0 ); $top->Entry( -textvariable => \$items{$item}[0], -width => 5, -relief => 'solid', #will show gridlines )->grid( -row => $row, -column => 1 ); $top->Entry( -textvariable => \$items{$item}[1], -width => 5, -relief => 'solid', #will show gridlines )->grid( -row => $row, -column => 2 ); $row++; } MainLoop();

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1001015]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2014-09-22 09:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (185 votes), past polls