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

I'm trying to make a window appear using Perl/Tk on Win32 that pops up, lets other stuff in the script execute, then goes away, ie, a "Wait" box. The obvious solution being using Tk::WaitBox, which draws a nice box. But I'm having a problem running the rest of the script while the box stays there. I've tried:

my $top2 = MainWindow->new(); my $waitbox = $top2->WaitBox(-title=>"Connecting to agent $port", -txt1=>"Connecting to Agent $port.\nConnection will be establ +ished when this box closes.\n", -cancelroutine=>sub { print "\nCancelling...\n"; $top2->unShow; die} ); fork and $waitbox->Show; #do some non-graphical background stuff in here $waitbox->unShow; MainLoop(); <p>

But this seems to consistently cause a page fault in TK.DLL.

Ideas on how to implement this?

Thanks,

Glenn

Replies are listed 'Best First'.
Re: Perl/Tk and "wait" box
by kschwab (Vicar) on Aug 17, 2001 at 03:02 UTC
    • Lose the fork(), you don't need it. I don't know about Windows, but Tk doesn't survive a fork() on unix. Basically, you can't share a window hierarchy with a child process.
    • The gui itself won't appear until MainLoop(); is entered, unless you muck with Tk::DoOneEvent or something. (update: see another node in this thread for a better answer here )
    • You never pack() any of the windows.
    • So, you have to resort to some trickery to get the main window posted and your "Connecting to agent" code running. I'm sure there's several ways, but Tk::After is what comes to mind for me.

      This is untested, but may be a good start:

      #!/usr/bin/perl my $top2 = MainWindow->new(); my $waitbox = $top2->WaitBox(-title=>"Connecting to agent $port", -txt1=>"Connecting to Agent $port.\nConnection will be establ +ished when this box closes.\n", -cancelroutine=>sub { print "\nCancelling...\n"; $top2->unShow; die} ); # pack the widgets $waitbox->pack; # encapsulate the wait box posting # and the connect routine in a sub # ( the waitbox is just using a "grab" and "focus", # if you want to roll your own, see Tk::Grab ) sub doyourstuff { # post the waitbox, this doesn't block # the process, it just grabs all the keyboard # and mouse events and discards them for a while $waitbox->Show; # do your connect stuff here for (1..10) { print STDERR "waiting $_\n"; sleep(1); } # get rid of the waitbox and start taking mouse/kb # events again. $waitbox->unShow; } # schedule the doyourstuff subroutine to # run in 0 ms $top2->after(0,\&doyourstuff); MainLoop();
      You can display and update TK windows without ever using MainLoop()
      There are two methods you can call to do this $widget->idletasks; and $widget->update; idletasks will not take new input into account, update will.
      You can look at the Tk::Widget docs to find out more about them.
      Hmm, interesting method. However, with my code it causes an invalid page fault in perl56.dll (using ActivePerl build 628). I'm going to play around with it, as it's entirely possible it's my code - the "connect" sub in my case fork()'s a couple of other subs found later in the code (this works the way I had it before).

      Anyway, I'll keep playing.

      Thanks,

      Glenn

      OK, with some tweaking the wait box and your code suggestion runs fine - however there seems to be an issue with Tk::WaitBox and it's "cancel" button feature - ie, the button displays, but it's unclickable - the mouse cursor sits on an hourglass when it's over the box, can't click anything.

      I've been trying to create my own wait box, but for some reason I'm running into a similar problem I had before - except this time it seems to be bypassing the "connect" sub completely and just displays my wait box.

      further suggestions appreciated.

      Thanks,

      Glenn

Re: Perl/Tk and "wait" box
by mattr (Curate) on Aug 20, 2001 at 14:42 UTC
    You also might want to check out POE which is an event-driven application framework that sounds like what you need.