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

pack manager was never my strong point. I need to pack items A,B,C,D (etc) in a frame in the following manner (basically a two by n grid):
|--------------------------------------| ||----------------||------------------|| || A || B || ||----------------||------------------|| ||----------------||------------------|| || C || D || ||----------------||------------------|| | . . . | |--------------------------------------|
So far, I've tried various combinations like but that's not right
A->pack(-side=>'left'); B->pack(-side=>'right'); C->pack(-side=>'left'); D->pack(-side=>'right');
Each row of two widgets is added from a routine, so I don't necessarily know what, if any rows were packed before. Please help :-)

Replies are listed 'Best First'.
•Re: Tk::pack help
by merlyn (Sage) on Aug 03, 2004 at 19:28 UTC
      The rest of my GUI is a pack geometry. how can i mix pack and grid?
Re: Tk::pack help
by davidj (Priest) on Aug 03, 2004 at 19:35 UTC
    You could do it with pack by putting cells A and C in a frame (and ->pack(-side=>'top') and cells B and D in a frame (and ->pack(-side=>'top'). Then the frames you would ->pack(-side=>'left').

    That being said, merlyn is right. The grid geometry manager is better suited for such a layout.

    davidj

        You are correct about that. However, before I was turned on to the grid and form geometry managers, I was able (with some difficulty and complexity) to get fairly decent grid layouts using pack. By all means, it is not the way to go and grid/form are the best options.

        davidj

Re: Tk::pack help
by sleepingsquirrel (Chaplain) on Aug 03, 2004 at 20:25 UTC
    #!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; my $top_frame = $mw->Frame()->pack(-side => "top"); my $bot_frame = $mw->Frame()->pack(-side => "top"); $top_frame->Button(-text => "A",)->pack(-side => "left"); $top_frame->Button(-text => "B",)->pack(-side => "left"); $bot_frame->Button(-text => "C",)->pack(-side => "left"); $bot_frame->Button(-text => "D",)->pack(-side => "left"); MainLoop;


    -- All code is 100% tested and functional unless otherwise noted.
      Maybe closer to your needs...
      #!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; for (["A","B"],["C","D"],["E","F"],["G","H"]) { my $frame = $mw->Frame()->pack(-side => "top"); $frame->Button(-text => "$_->[0]",)->pack(-side => "left"); $frame->Button(-text => "$_->[1]",)->pack(-side => "left"); } MainLoop;


      -- All code is 100% tested and functional unless otherwise noted.
Re: Tk::pack help
by rinceWind (Monsignor) on Aug 04, 2004 at 09:31 UTC
    Others (Randal especially) are right about grid being a more suitable geometry manager. There is nothing to stop you from putting a frame inside a grid cell, and then using pack as the geometry manager for the frame.

    I tend to use grid cells for columns that I want to line up, and frames with pack if a cell needs to contain multiple items that don't line up (with anything outside the cell).

    As an example of getting the best out of grid, see the RPN calculator tutorial on the Tk wiki.

    --
    I'm Not Just Another Perl Hacker

Re: Tk::pack help
by Elderian (Sexton) on Aug 05, 2004 at 06:00 UTC
    Heya,

    i played around a little bit with pack, but it seems to be impossible with a single pack. I could imagine to ways of solving it:

    1. As some monks already mentioned, grid would be the geometry manager, which is most suitable for this task.

    2. Untested: If it is possible to insert a frame into a frame, you could try the following code:
    my $topframe = $mainWindow->Frame; $topframe->pack(-expand => 'x', -fill => 1); my $leftframe = $topframe->Frame; $leftframe->pack(-side => 'left', -expand => 'x', -fill =>1); my $rightframe = $topframe->Frame; $rightframe->pack(-side => 'left', -expand => 'x', -fill =>1);
    ... but using grid is much easier to and to understand.

    Elderian
      With this approach vertical alignment of the widgets in the frames could be difficult. Here's a hack to use pack() with helper frames to form a gridded structure.
      #!/usr/bin/perl use strict; use List::Util qw(max); use POSIX qw(ceil); use Tk; my $mw = new MainWindow(); my @fields = ("Name", "Street", "Postal code", "City"); my @l; for (@fields) { my $f = $mw->Frame->pack(-fill => "x"); my $l = $f->Label(-text => $_, -anchor => "w")->pack(-side => "lef +t"); push @l, $l; my $e = $f->Entry->pack; } my $maxwidth = max map { $_->reqwidth } @l; my $fontwidth0 = $mw->fontMeasure($l[0]->cget("-font"), "0"); my $maxwidth_chars = ceil($maxwidth / $fontwidth0); for (@l) { $_->configure(-width => $maxwidth_chars); } MainLoop;
      The hack is to set the -width option of the labels to get a uniform width for the left column. In the sample script above this is done dynamically by extracting the width of the largest label. Unfortunately specification of widths is done in characters, but the reqwidth() method returns pixels, so an additional conversion is necessary.