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

Howdy,


I'm wondering about the following in my code:

1. My code barfs shortly after clicking on the "About..." Is it possible to make the Toplevel $tl modal (i.e. hold focus until the close button is depressed)? If so, how?

2. I've had to comment out strict because I'm not sure exactly how to pass the $mw from main to the sub do_toplevel. Can I safely use strict in a Tk program? If so, what syntax could I use to send $mw along?

#!perl -w =pod IP & Hostname GUI Program v .3 slojuggler =cut #use strict; use Socket; use Sys::HostIP; #For hostname use Sys::Hostname; my $ipaddr = hostip; print "Mine: $ipaddr \n"; my $hostnm = hostname(); print "Host $hostnm \n"; use Tk; my $mw = MainWindow->new; $mw->title("Your IP Info"); $mw->Label(-text=>"IP Address -> $ipaddr") ->pack(-fill => 'x', -side=>"top", -ipadx=>20); $mw->Label(-text=>"Hostname -> $hostnm") ->pack(-fill => 'x', -side=>"top"); $mw->Button(-text=>"Done!", -command=> sub { exit } ) -> pack (-side=> +"bottom"); #Somehow pass the $mw to the do_toplevel routine, to keep in step with + use strict #$mw->Button(-text=>"About...", -command=> \&do_toplevel + $mw arg som +ehow??? } ) -> pack (-side=>"bottom"); $mw->Button(-text=>"About...", -command => \&do_toplevel ) -> pack (-side=>"bottom +"); MainLoop(); sub do_toplevel { #Somehow pick up the $mw by using something like the following? #my $tl = shift or whatever it takes to bring in the passed in var +; ??? my $tl = $mw->Toplevel(); $tl->title("Aboutl"); $tl->Button(-text => "Close", - command => sub {$tl->destroy})->pack; $tl->waitWindow(); }

Thanks... --slojuggler

Replies are listed 'Best First'.
Re: Modal Tk Toplevel/Passing a MainWindow
by kschwab (Vicar) on Sep 08, 2001 at 18:00 UTC
    1. You could:
    • Roll your own focus/grab management with $widget->grab and $widget->focus. See grab and focus. You may also want to see the "busy" method mentioned in Tk:Widget.
    • Use a prebuilt widget like Tk::Dialog (can't find the docs) or Tk::DialogBox. These automatically take focus, do a grab, and release once the modal dialog is answered.

    2. Have a look at Tk::Callbacks. In your case,  -command => [\&do_toplevel,$mw] ) should work. ( You could then use shift() as you mentioned, to get at $mw )

Re: Modal Tk Toplevel/Passing a MainWindow
by chromatic (Archbishop) on Sep 08, 2001 at 22:42 UTC
    Another approach is to use an anonymous function. Hey, it's even a closure!
    $mw->Button( -text=>"About...", -command=> sub { do_toplevel($mw) } } )-> pack (-side=>"bottom");
    It's the same sort of thing you do later on for the Close button in do_toplevel(). :)
      chromatic/kschwab, Thanks for your help! I played with DialogBox and it does the job. Both the anonymous method as well as the [] methods work well for passing. Is one method preferred to the other, or should I go by the TMTWOTDI way?

      Curious, is there a module or a Tk Option I can use to center the initial MainWindow ($mw). When I run the current code, the $mw pops up in a fairly random place, yet the DialogBox shows up dead center. This gets a little visually startling.

      The code now looks like this:

      #!perl -w =pod IP & Hostname GUI Program v .3 slojuggler =cut #use strict; use Socket; use Sys::HostIP; #For hostname use Sys::Hostname; print "@INC" . "\n"; my $ipaddr = hostip; print "Mine: $ipaddr \n"; my $hostnm = hostname(); print "Host $hostnm \n"; use Tk; use Tk::DialogBox; my $mw = MainWindow->new; $mw->title("Your IP Info"); $mw->Label(-text=>"IP Address -> $ipaddr") ->pack(-fill => 'x', -side=>"top", -ipadx=>20); $mw->Label(-text=>"Hostname -> $hostnm") ->pack(-fill => 'x', -side=>"top"); $mw->Button(-text=>"Done!", -command=> sub { exit } ) -> pack (-side=> +"bottom"); #Somehow pass the $mw to the do_toplevel routine, to keep in step with + use strict #$mw->Button(-text=>"About...", -command=> sub { \&do_toplevel ????? } + ) -> pack (-side=>"bottom"); $mw->Button(-text=>"About...", -command => sub { do_toplevel($mw) }) -> pack (-sid +e=>"bottom"); MainLoop(); exit(); sub do_toplevel { my $mainwindow = shift; my $dialog = $mainwindow->DialogBox(-title => "About...", -buttons + => ["OK"]); my $label = $dialog->add('Label', -text=>"V1.2")->pack(-fill=> 'x' +, -side=>"top"); $dialog->Show; =pod my $tl = $mainwindow->Toplevel(); $tl->title("About..."); $tl->Button(-text => "Close", - command => sub {$tl->destroy})->pack; $tl->waitWindow(); =cut }