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

Hello, all,

At work we're in the process of transferring to a new set of systems. The old systems are Solaris 8 machines, with Perl 5.6 and Tk400.202. The new systems are a Linux machines. The Linux machines have a corporate provided Perl 5.8.8, and we have the distribution provided Perl 5.10. Both of the perls installed have Tk804.027. When we started testing the new systems, though, we started having problems, which seem localized to programs using Tk. The major problem that we have that we can't seem to find a solution to is window resizing. For example, in the following code, the window resizes at the beginning, but when the 'Continue' button is selected, the window immediately shrinks, but never expands after the next set of frames are packed.
#!/usr/bin/perl -w use Tk; use Tk::Label; use Tk::Button; use Tk::Menubutton; use Tk::Menu; use Tk::LabEntry; use Tk::Dialog; use Tk::DialogBox; use Tk::Frame; $mw = MainWindow->new(); get_job(); $mw->update; MainLoop(); sub get_job { $wjLabEntry = $mw->Frame(-bg => "wheat1")->pack(); my $jobentry = $wjLabEntry->Entry(-width => 10)->pack(-side +=> 'left'); $mode_buttons = $mw->Frame(-bg => "wheat1")->pack(); my $DoButton = $mode_buttons->Button(-text => 'Continue', -command + => sub {&do_setup()} )->pack (-side => 'left', -expand => 1); my $QuitButton = $mode_buttons->Button(-text => 'Quit', -command = +> sub {Tk::exit} )->pack (-side => 'left', -expand => 1); my $HelpButton = $mode_buttons->Button(-text => "Help", -command = +> sub {&HelpTxt} )->pack (-side => 'left', -expand => 1); $jobentry->focus; $jobentry->bind('<Return>',sub {$DoButton->focus}); } sub do_setup { if (Exists $wjLabEntry) { $wjLabEntry->destroy; $mode_buttons->destroy; $wjLabEntry = $mw->Frame(-bg => "wheat1")->pack(); $mode_buttons = $mw->Frame(-bg => "wheat1")->pack(); my $QuitButton = $mode_buttons->Button(-text => "Terminate", - +command => sub {Tk::exit} )->pack (-side => 'left', -expand => 2); my $HelpButton = $mode_buttons->Button(-text => "Help", -comma +nd => sub {&HelpTxt} )->pack (-side => 'left', -expand => 2); $HelpButton->bind('<e>',\&HelpTxt); $mode_buttons->update; $mw->update; } $PartStep = $mw->Frame(-bg => "wheat1")->pack(-fill => 'both'); my $DrillButton = $PartStep->Button(-text => 'DRILL/ROUT', -comman +d => sub {&getDrill();&CleanUp();} )->pack(-side => 'left'); my $ToolButton = $PartStep->Button(-text => 'TOOLING', -command => + sub {&getTool();&CleanUp();} )->pack(-side => 'left'); my $AllButton = $PartStep->Button(-text => 'All', -command => sub +{&getTool();&CleanUp();} )->pack(-side => 'right', -fill => 'x', -expand = +> 1,); $mw->update; }
Anyone have any idea why that code shouldn't resize the window?

Replies are listed 'Best First'.
Re: Problems after upgrading both Perl and Tk
by graff (Chancellor) on Jul 10, 2009 at 19:27 UTC
    Okay, let me start over and try again. My previous reply was totally irrelevant (though I do like the cleaner technique, which I hope is helpful in its own right).

    I managed to get consistent and (presumably close to) intended resizing results by changing this:

    $wjLabEntry->destroy; $mode_buttons->destroy; $wjLabEntry = $mw->Frame(-bg => "wheat1")->pack(); $mode_buttons = $mw->Frame(-bg => "wheat1")->pack();
    to this:
    $_->destroy for ( $wjLabEntry->children ); $_->destroy for ( $mode_buttons->children );
    That might not end up doing exactly what you want, but at least the window remains large enough to be usable and in fact gets bigger as needed. And at least it makes a certain amount of sense: Tk's pack manager will work better if the containing frames remain intact, as opposed to being destroyed and rebuilt from scratch.

    Apart from that, if you pass those two frame widget handles as params to "do_setup" when calling it from get_job, you would be able to add "use strict" without any additional global variables, which would be a Good Thing.

    And you can drop all the use Tk::*; lines -- just use Tk; will suffice. Ditto for all the  $mw->update calls (those just aren't needed in this situation).

    FINAL UPDATE: I'm guessing that the unpredictable behavior I was seeing with the OP code is probably related to the relatively recent Perl 5 feature that enhanced the security of hash key management -- this feature may have been missing in the ancient Solaris environment that the OP code came from, and in that old environment the code was probably always working because the Tk internal hashes were always being stored (and accessed/destroyed) in a consistent order. That consistency goes away in current Perl versions, which could mean that from one run to the next, calling "destroy" on the two frames that make up your entire MainWindow might cause variable results, depending on what gets destroyed first... But that's just a guess.

    Anyway, I also noticed that since you don't seem to use the "$wjLabEntry" frame ever again, you can destroy that one, and just keep the "$mode_buttons" frame (destroying its children only). That would probably result in the appearance that you really want.

      Works like a charm, thanks so much.

      I'm suspecting that you're right with the reasoning behind the cause of the sudden change. I was thinking along the same lines, but couldn't find much reference online that steered me towards the reasons.

      I also appreciate the style guides, but I'm afraid that this code belongs to one of my coworkers, and fixing it only fell to me since I'm handling the Linux conversion. I seem to be the only person here that really wants to do any kind of 'best practice' style of coding. The segment of code I posted was ripped out of a much larger piece of software which likely would have made you cringe if you'd seen it. ;)

      UPDATE: Bah. Still this thing taunts me. If you go a little farther down in the code, there's another MainWindow Frame that gets created, $PartStep. Everything packs and resizes properly up until that appears. Now it's just that section, but I still have to grab the bottom of the window and pull it down until it's tall enough to show that section.

      UPDATE TO THE UPDATE: Seems the solution to this was to move the point where $PartStep got created. I moved the creation/pack up to where the others got created, and then left the population part where it was, and that seemed to take care of the problem.
Re: Problems after upgrading both Perl and Tk
by graff (Chancellor) on Jul 10, 2009 at 18:33 UTC
    I was able to see the resizing problem you described (using darwin, Perl 5.8.8, Tk 804.028). It stopped It became (or remained?) unpredictable when I changed the values assigned to the -command parameters in the widget creations.

    Instead of this (whitespace adjusted for legibility):

    my $DoButton = $mode_buttons->Button( -text => 'Continue', -command => sub {&do_setup()} )->pack (-side => 'left', -expand => 1);
    Try it like this:
    my $DoButton = $mode_buttons->Button( -text => 'Continue', -command => \&do_setup ### provide a code_ref, not anon_ +sub )->pack (-side => 'left', -expand => 1);
    Also, wherever you had this:
    ... -command => sub {&getTool();&CleanUp();},
    I would replace it with:
    ... -command => sub {getTool();CleanUp();}, ### drop the "&"
    just on general principles.

    I'm not sure I can explain why the difference seems to matter, but I should have known that such a change would just be cosmetic -- no reason it should affect behavior -- but still, wherever a -command parameter is simply supposed to invoke a sub with no args, the value of that parameter should be the code_ref that points to that sub.

    And whenever you need to pass args to the subroutine, provide an anon.array containing the code ref and the args:

    ... -command => [ \&func_name, $arg1, $arg2 ],

    UPDATE: NEVERMIND! This is stranger than I thought -- the behavior I'm getting is not actually following a pattern yet. I'm seeing alternations between "resizes as intended" and "shrinks to unusable size". Perhaps someone else will figure it out while I'm struggling with this...

Re: Problems after upgrading both Perl and Tk
by Anonymous Monk on Jul 10, 2009 at 17:13 UTC
    It works for me with perl, v5.8.9 built for MSWin32-x86-multi-thread with Tk 804.027