http://qs1969.pair.com?node_id=942239


in reply to Re^5: resizing problem with Tk appl using PackForget
in thread resizing problem with Tk appl using PackForget

sure; I don't blame anyone in being a monkey. Just thought adding more code would clobber...

I tried the $mw->geometry(undef); this works great when hiding the to be hidden widgets. So far so good.
But then when restoring the hidden, they are restored to their 'required' width and height, rather than those they had when they were 'packForgotten'.
This seems to be the effect of the $mw->geometry(undef); call

There is a diff between:
$mw_w = $mw->width; $mw_h = $mw->height;
and
$mw_w = $mw->reqwidth; $mw_h = $mw->reqheight;
After many tries I found a solution (?) by remembering the geometry of the MW when hiding:
$mw_geom = $mw->geometry();
and restoring this when re-packing:
$mw->geometry($mw_geom);
So I can add that to my code in some way or another. Only thing is that I do not understand it yet ;-(

Replies are listed 'Best First'.
Re^7: resizing problem with Tk appl using PackForget
by zentara (Archbishop) on Dec 07, 2011 at 18:25 UTC
    What you can also add is code to watch for the resize event, occuring while the Frames are unpacked. You can keep a running array of the current window size.

    It seems to me that repacking your children into larger frames might be accomplished by using -fill=>both -expand=>1 in the packing, and then calling the packPropagate command.... but that is untested.

    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = new MainWindow; my $current_size = $mw->reqwidth . "x" . $mw->reqheight; my $old_current_size = $current_size; $mw->bind( '<Configure>', sub{ &OnResize }); my $leave = 0; $mw->bind( '<Leave>',sub { $leave = 1; } ); $mw->bind( '<Enter>',sub { $leave = 0; &OnResize; } ); MainLoop; sub OnResize { my $current_size = $mw->width . "x" . $mw->height; if( $leave == 1) {return } if($old_current_size eq $current_size){return} ## Resize has occurred do something: printf( "Resize happened - old size: %s, new size: %s\n", $old_current_size, $current_size ); ## set the old size to the new size $old_current_size = $current_size; }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      The binding for the resizing is a good idea, since I'm not sure yet what would happen exactly when resizing (manually) between my hide/show actions.

      Still, if I'm honest, I think this is a limitation of Tk: imho their should be more automatic resize options than me coding and remembering the size of all frames. For my app this is still doable, but for larger apps this would become very cumbersome!
      Well, I probably just have to live with it; maybe someone will make a widget->hide() and widget->restore() to ease doing this. thx for your help !
        Still, if I'm honest, I think this is a limitation of Tk: imho their should be more automatic resize options than me coding and remembering the size of all frames.

        Well, I think it maybe a widget layout design problem on your part, which probably can be easily fixed by carefully allowing all the child widgets to repack themselves, according to the new size.

        If you want to remove a frameful of widgets, you should remove it's child widgets first with packForget. (Its like you can't remove a directory which still has subdirs). In other words, don't use complete Frame removal to remove a set of widgets, remove each widget itself, and leave the Frame. Then when you do a resize, and want to repack your frame, each widget gets repacked, and will do so according to the new reported size of the Frame they are being packed into.

        I hope that made sense. Play with the following code, it creates new widgets on a rebuild, but you could repack your hidden widgets instead. A second example is also provided.

        #!/usr/bin/perl use warnings; use strict; use Tk; my $top = new MainWindow; my @counts = ('a'..'z'); my %cbuttons; my $frame = $top->Frame()->pack(); setup_page(); $top->Button(-text => "packForget", -command => sub{ my @w = $frame->packSlaves; foreach (@w) { $_->packForget; } })->pack(); $top->Button(-text => "repack", -command => sub{ &setup_page })->pack(); $top->Button(-text => "Exit", -command => sub {exit})->pack; MainLoop; sub setup_page{ for (1..4){ my $text = shift @counts; $cbuttons{$_}{'cb'} = $frame->Checkbutton( -text => $text, -variable => \$cbuttons{$_}{'val'}, -command => \&SetState, )->pack; } }
        A second example:
        #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; my $vh = $mw->vrootheight; my $vw = $mw->vrootwidth; $mw->geometry($vw.'x'.$vh.'+0+0'); $mw->overrideredirect(1); #grabs full control $mw->fontCreate('big', -family=>'arial', -weight=>'bold', -size=>int(-18*18/14)); my $topframe = $mw->Frame->pack(); my $frame = $mw->Frame->pack(); my $txt; #make these globals so you reuse them my $canvas; #and avoid memory gains of making too many #redundant widgets my $count = 0; # instead of a button you could make navigation arrows $topframe->Button(-text => "Change Screen", -command => sub{ #clean out frame's children my @w = $frame->packSlaves; foreach (@w) { $_->packForget; } #clean out frame $frame->packForget; $count++; &build($count); })->pack(-side=>'left',-padx=>20); $topframe->Button(-text => "Exit", -command => sub {exit})->pack(-side=>'right',-padx=>20); &build(0); #setup first screen MainLoop; sub build { my $count = shift; $txt = $frame->Text(-bg=>'white',-font=>'big',-height=>5)->pack(-fill +=>'x'); $txt->insert('end',"\t\t\t\t Page $count"); # Note that the 'virtual window' height and width are $vh and $vw # respectively, so we use those dimensions for our Canvas height # and width, and let the Canvas expand and fill in both x and y # directions. # $canvas = $frame->Canvas( -width => $vw, -height => $vh, -background =>'blue', )->pack(-expand => 1, -fill => 'both'); $canvas->createRectangle(80, 80, 200, 200, -fill => 'yellow'); $canvas->createText(125, 125, -fill => 'black', -text => "page $count", -font => 'big', ); $frame->pack(); #reshow it $mw->update; }

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