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

I am writing my first application in Perl/tk, and I'm having trouble dealing with screen transitions. Basically, I want a full-screen app. From the main menu, the user can move to a number of different screens and then eventually find their way back to the main menu.

Right now, I'm destroying the main window and re-creating it for each different screen layout.

$mw = new MainWindow;
to create it and
$mw->destroy;
to destroy it.

Then, for the next screen, I just create the main window again. I don't know if this is likely to cause me trouble in the future or not.

NOTE: This also means that I have multiple MainLoop calls - one for each screen. I don't know if this is very bad GUI programming style or not.

I'm currently having trouble giving focus to my "new" main window that appears after the user makes a selection from the main menu. The focus is transferred to my console window (probably when I destroy the main window), but I can't get it back to the main window once another one is created. I'm now experimenting with Toplevel windows and they appear to behave better, but this may introduce different problems.

I've been searching for guidance on this fundamental aspect of GUI programming, but I have not found any reference to it in Mastering Perk/Tk or on-line searches.

I'm stumbling around in the dark on this one. Could someone out there with Perl/tk experience please give me some advice?

Thank you very much for any suggestions.

Replies are listed 'Best First'.
Re: Perl/tk - how to handle screen transitions - can I destroy the main window?
by Joost (Canon) on Mar 28, 2008 at 22:01 UTC
    Currently, I'm using Tk::Notebook for this kind of thing, and I used this little hack to remove the tabs at the top of the notebook:

    # at the top of the program, after loading Tk::Notebook sub Tk::NoteBook::InitTabSize { my $nb = shift; $nb->{'pad-x1'} = 0; $nb->{'pad-x2'} = 0; $nb->{'pad-y1'} = 0; $nb->{'pad-y2'} = 0; $nb->{'minW'} = 0; $nb->{'minH'} = 0; }
    It's a pretty ugly hack, but it works like a charm. No multiple mainloops or anything like that needed, you just do $notebook->add() to add "screens" and $notebook->raise($name_of_screen) to raise the screen you want.

      that is just wrong (for so many reasons)
Re: Perl/tk - how to handle screen transitions - can I destroy the main window?
by JStrom (Pilgrim) on Mar 28, 2008 at 21:46 UTC
    Why not place each page in a Tk::Frame, then use packForget to remove the current one from the main window then pack a new one? Sort of like Java's CardLayout:
    use Tk; $mw = MainWindow->new; $page[0] = $mw->Frame(); $page[1] = $mw->Frame(); $page[0]->Button( -command => sub { setpage(1) }, -text => 'Go Page 2! +' )->pack(); $page[1]->Button( -command => sub { setpage(0) }, -text => 'Back to 1' + )->pack(); $page[0]->pack(); $curpage = 0; MainLoop; sub setpage { my $n = shift; $page[$curpage]->packForget(); $page[$n]->pack(); $curpage = $n; }
Re: Perl/tk - how to handle screen transitions - can I destroy the main window?
by zentara (Cardinal) on Mar 29, 2008 at 16:43 UTC
    Using the packForget idea, here are an assortment of various tips to get you going. Remember to reuse your widgets, whichever ones you choose.
    #!/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 $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); #make these widgets globals so you reuse them #and avoid memory gains of making too many #redundant widgets my $txt = $frame->Text(-bg=>'white',-font=>'big', -height=>5)->pack(-fill=>'x'); # 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. # my $canvas = $frame->Canvas( -width => $vw, -height => $vh, -background =>'blue', )->pack(-expand => 1, -fill => 'both'); &build(0); #setup first screen MainLoop; sub build { my $count = shift; #clean out old txt and reuse widget, the pack it again $txt->delete('1.0','end'); $txt->insert('end',"\t\t\t\t Page $count"); $txt->pack(-fill=>'x'); #clean out old canvas and reuse widget, the pack it again $canvas->delete('all'); $canvas->createRectangle(80, 80, 200, 200, -fill => 'yellow'); $canvas->createText(125, 125, -fill => 'black', -text => "page $count", -font => 'big', ); $canvas->pack(-expand => 1, -fill => 'both'); $frame->pack(); #reshow it by repacking the new frame $mw->update; }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum