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

Ok Monks,
Say I got these two gui scripts with their own Tk Mainloop where I from the first one wanna start the second one when one presses a button for instance. Now, this doesnt work just "running" the script with the do function nor the require function. Anyone here got some nice solutions for this, besides adding the code from script #2 into script #1 and just use one Mainloop? I prefer the module stype version more where one can devide different guis like this. Like seperate programs...
Btw, when I close the started GUI #2, I wanna be able of returning to GUI #1, where I left off.

Thanks,
Ace

Replies are listed 'Best First'.
Re: Starting another Tk GUI MainLoop
by GrandFather (Saint) on Jul 18, 2005 at 02:50 UTC

    If you want them to behave like seperate programs why not just run the second script as a second program?

    Probably using backticks is the easiest way to do that:

    ... #run the second script `Perl secondscript.pl`; #resumes here when second script terminates

    Perl is Huffman encoded by design.
      Is this gonna work with PAR (PP) aswell? (Meaning having all those merged into a STANDALONE file...)

        In this case it likely will as you can be pretty sure the system will be able to find Perl, regardless of what system it is, and backticks work pretty much anywhere.


        Perl is Huffman encoded by design.
Re: Starting another Tk GUI MainLoop
by graff (Chancellor) on Jul 18, 2005 at 03:23 UTC
    Do you expect (or need) to be able to do anything with GUI #1 while GUI #2 is running? If it's okay for GUI #1 to "freeze" (be idle, not respond to any user input events) while you use GUI #2, then Grandfather's suggestion, using backticks or a system() call in #1 to run #2 as a separate program, should work out fine. Execution in #1 will wait until #2 exits.

    But if you need to use both GUI's while #2 is on the screen, then you'll want a modified version of #2 that has everything except the Mainloop call. If all the widget creation stuff is not already in a sub, just wrap it all in a sub. Put "1;" at the end of the script.

    Then, add the appropriate "require" statement to the #1 script, and the button in GUI #1 that brings up #2 just has to call the one sub that creates all the widgets (including #2's mainwindow). Oh, and if #2 has a button that invokes "exit", change that to just destroy #2's mainwindow, so that #1 doesn't get shut down as well.

    update: one last point to consider: if you've been good, and already have "use strict" in both scripts and are not mucking around with global variables, then folding the scripts together this way into a single program should work out just fine. But if you haven't been good, this exercise may very well educate you in the wisdom of stricture. (I know that with Tk scripts, it can be hard to avoid the use of globals in many situations. But it can be done.)

    (one more update: If you happen to be using any unix-like OS, you could have both GUI's running as separate programs and both responding to user input, by passing the #2 command line string to "system()" with an ampersand at the end of the line, to run that program in the background -- e.g.  system( "gui2 arg1 arg2 &" );. I'm not a windows user, so I don't know if this works for windows, but maybe it does, or maybe there's something for windows that is equivalent to running a background job. This could also mean that every time you push that button in #1, you start another #2 window running -- you could have any number of secondary GUI's going on at once, which might be very good, or very bad, depending...)

Re: Starting another Tk GUI MainLoop
by Ultra (Hermit) on Jul 18, 2005 at 09:11 UTC

    MainLoop started in script #1. Also, script #1 has a button, "Start #2".

    Transform script #2 into a "standalone" widget, something like:

    package Widget2; Construct Tk::Widget 'Widget2'; use Tk; use Tk::Frame; # go ahead and create elements in the widget, like it would be a # standalone app (don't forget to add the close button :D

    Somewhere in #1 you have ...

    sub load_tool { my $class = shift; my $wdg_plugin; #plugin's own widget eval { require $class . ".pm"; if ( "$class"->isa("Tk::Widget") ) { #If there is a UI then load as widget $wdg_plugin = $mw->$class( #we're sending references )->pack(); } }; #if any errors occurred, report them if ($@) { my $msg = "Initialization of tool $class failed:\n\n"; } }

    I hope you got the idea ...

    Dodge This!
      Ok, this is insteresting. Allthough I wanna avoid doing #2 as a module (or I still can run it as a standalone, eventough its a module?), this is quite nice...
      Ok, just tested this. Application exists when I press the button! So, doesnt really work. Behaves kinda like "require" if I reacall correctly... Seems all works fine until the Mainloop thingy...

      Update: Apparently it DOES work.. Even only with do ("script.pl")!! Fonky. Reason for the exit is that I had exit after the Mainloop statement (dont ask my why). Seems though that somehow the gui pops up nicely without the Mainloop... (But still only one Mainloop is in the works apparently!)
      However, now I got a small "problem" with functions beeing redefined when I press the button again.
Re: Starting another Tk GUI MainLoop
by zentara (Cardinal) on Jul 18, 2005 at 10:44 UTC
    It sounds like you want to "fork-and-exec" the second program, then it will run it's own mainloop in a separate process. If you just want a button to launch it, look at Tk::ExecuteCommand, which can be incorporated into your program #1, to launch program #2. Your big concern is whether you need "data" returned from prog #2 to be used by prog #1.

    I'm not really a human, but I play one on earth. flash japh
      Gonna check this out aswell. This time I dont think I need to any communication between the two scripts... (return data from #2 to #1). In this case the answer from Ultra seems better.