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

Hello Monks

I have a GUI written in Tk. I have created a custom status bar (script below) to be put at the bottom of the GUI. The status bar has three elements: a) left side: a variable message for the user; b) center: a paging menu and c) right: a progress bar. All three parts are optional, i.e. I display them only if needed by the current actions. What I would like to achieve is that part b) is always centered in the Frame, no matter what the left label looks like or if the progressbar is shown or not. Is it possible to have this Frame always centered using pack?

use strict; use warnings; use Tk; use Tk::ProgressBar; my $mw = MainWindow->new(); my $percent_done; my $UserMessage; my $PagingMessage="10 of 20"; my $UserMessage="this is my user message"; $mw->Label( -anchor => 'w', -relief => 'flat', -textvariable => \$UserMessage, )->pack(-side => 'left', -expand => 0 , -fill =>'both'); my $FramePaging = $mw->Frame()->pack(-side=>'left', -padx=>20, -fill=> +'none' ); my $ButtonPagingNext = $FramePaging->Button( -text=> " Next > ", )->pack(-side => 'right', -anchor=>'center', -expand => 1 , -f +ill =>'both'); my $WidgetShowPaging = $FramePaging->Label( -anchor => 'w', -relief => 'flat', -textvariable => \$PagingMessage, )->pack(-side => 'right', -anchor=>'center', -expand => 1 , -f +ill =>'both'); my $ButtonPagingPrevious = $FramePaging->Button( -text=> " < Previous ", )->pack(-side => 'right', -anchor=>'center', -expand => 1 , -f +ill =>'both'); $mw->ProgressBar( -width => 20, -length => 200, -anchor => 'w', -from => 0, -to => 100, -blocks => 1, -colors => [0, '#93ff66', 50, '#ffff66' , 80, '#dc143c'], -variable => \$percent_done )->pack(-side=>'right', -padx=>5, -pady=>5, -fill=>'x' ); $mw->MainLoop();

Replies are listed 'Best First'.
Re: Tk geometry problem with pack
by tybalt89 (Monsignor) on May 28, 2019 at 02:15 UTC

    Here's a first rough pass at it.

    #!/usr/bin/perl use strict; use warnings; use Tk; use Tk::ProgressBar; my $mw = MainWindow->new(); $mw->geometry( '+500+500' ); # for testing $mw->Frame(-bg => 'green', -width => 700, -height => 10)->pack; my $percent_done; my $UserMessage; my $PagingMessage="10 of 20"; $UserMessage="this is my user message"; my $subw = $mw->Frame(-height => 50)->pack(-expand => 1, -fill => 'bot +h'); $subw->Label( -relief => 'flat', -textvariable => \$UserMessage, )->place( -relx => 0, -rely => 0.5, -anchor => 'w'); $subw->ProgressBar( -width => 20, -length => 200, -from => 0, -to => 100, -blocks => 1, -colors => [0, '#93ff66', 50, '#ffff66' , 80, '#dc143c'], -variable => \$percent_done )->place(-relx => 1, -rely => 0.5, -anchor => 'e'); my $FramePaging = $subw->Frame( )->place(-relx => 0.5, -rely => 0.5, -anchor => 'center'); my $ButtonPagingNext = $FramePaging->Button( -text=> " Next > ", )->pack(-side => 'right', -anchor=>'center', -expand => 1 , -f +ill =>'both'); my $ButtonPagingPrevious = $FramePaging->Button( -text=> " < Previous ", )->pack(-side => 'left', -anchor=>'center', -expand => 1 , -fi +ll =>'both'); my $WidgetShowPaging = $FramePaging->Label( -anchor => 'center', -relief => 'flat', -textvariable => \$PagingMessage, )->pack(-side => 'right', -anchor=>'center', -expand => 1 , -f +ill =>'both'); $mw->MainLoop();

      This seems to achieve my goal. But it is not considered bad practice to mix 2 different geometry managers, in your case Place and Pack?

        No, not that I know of.

        The rule is "all the immediate children of one parent must have the same geometry manager".
        I have often used both Pack and Grid in the same Tk app, just at different levels.

Re: Tk geometry problem with pack
by AnomalousMonk (Archbishop) on May 28, 2019 at 05:58 UTC

    A frame-within-frame (within frame...) approach using pack can ease the problems of getting everything to "line up" the way you want. Another geometry manager might be better for an immediate problem, but pack is quite generally useful and the word on the street is that you don't want to mix geometry managers. I don't understand the exact layout you want, but this may serve as a point of departure to help you deal with your centering problems.
    File tk_centered_frame_3.pl:


    Give a man a fish:  <%-{-{-{-<

      I guess I live on a different street than you do :)

Re: Tk geometry problem with pack
by tybalt89 (Monsignor) on May 28, 2019 at 00:28 UTC

    I'm not sure ->pack can do that.

    Look at the ->place geometry manager.

Re: Tk geometry problem with pack
by Anonymous Monk on May 29, 2019 at 02:46 UTC
    #!/usr/bin/perl -- use strict; use warnings; use Tk; use Tk::ProgressBar; TheAnonymous(); TheAnonymousMonk(); sub TheAnonymous { use Tk; my $mw = tkinit; my $bf = $mw->Frame( -bg => 'pink', -height, 150 ) ->pack( qw/ -side bottom -fill x / ); my $tf = $mw->Frame( -bg => 'lightgreen', -height, 150 ) ->pack( qw/ -side top -fill x / ); $mw->Label( -text, 'Hit tab space , tab space , tab space , tab sp +ace' ) ->pack; $tf->Button( -text => 'center', -command => [ \&TheToggle, 2, $bf +] ) ->pack( qw/ -anchor center / ); $tf->Button( -text => 'left', -command => [ \&TheToggle, 0, $bf ] +) ->pack( qw/ -side left / ); $tf->Button( -text => 'right', -command => [ \&TheToggle, 1, $bf ] + ) ->pack( qw/ -side right / ); $bf->Pane( -bg => 'blue', )->pack( qw/ -side left / ); $bf->Pane( -bg => 'green', )->pack( qw/ -side right / ); $bf->Pane( -bg => 'red', )->pack( qw/ -anchor center / ); $mw->withdraw; $mw->geometry( '480x480' ); $mw->deiconify; $mw->focusForce; $mw->MainLoop; } ## end sub TheAnonymous sub TheAnonymousMonk { use Tk; my $mw = tkinit; my $bf = $mw->Frame( -bg => 'pink', -height, 150 ) ->pack( qw/ -side bottom -fill x / ); my $tf = $mw->Frame( -bg => 'lightgreen', -height, 150 ) ->pack( qw/ -side top -fill x / ); $mw->Label( -text, 'Hit tab space , tab space , tab space , tab sp +ace' ) ->pack; $tf->Button( -text => 'center', -command => [ \&TheToggle, 2, $bf +] ) ->pack( qw/ -anchor center / ); $tf->Button( -text => 'left', -command => [ \&TheToggle, 0, $bf ] +) ->pack( qw/ -side left / ); $tf->Button( -text => 'right', -command => [ \&TheToggle, 1, $bf ] + ) ->pack( qw/ -side right / ); $bf->Pane( -bg => 'blue', )->pack( qw/ -side left -expand 1 -fill +both / ) ->Label( -text, -left )->pack; $bf->Pane( -bg => 'green', ) ->pack( qw/ -side right -expand 1 -fill both / )->Label( -text, + -right ) ->pack; $bf->Pane( -bg => 'red', ) ->pack( qw/ -anchor center -expand 1 -fill both / ) ->Label( -text, -center )->pack; $mw->withdraw; $mw->geometry( '480x480' ); $mw->deiconify; $mw->focusForce; $mw->MainLoop; } ## end sub TheAnonymousMonk sub TheToggle { my( $kidid, $parent ) = @_; my $kid = ( $parent->children )[$kidid]; if( my %info = eval { $kid->packInfo } ) { delete $info{-in}; $kid->{"\0_packInfo"} = \%info; $kid->packForget; $parent->packPropagate; } else { $kid->pack( %{ delete $kid->{"\0_packInfo"} } ); } } ## end sub TheToggle