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

I'm new to Perl/Tk and have what I hope are a couple of basic questions about handling window exits. Actually this first one is probably more of a basic perl question...

1. I have a script that envokes a second Perl/Tk script to get some input from the user. The second is standalone because it's general purpose and I didn't want to rewrite it every place I want to use it. Anyhoo, I'm running this second script through a system call:

system("perl path_to_other_script");

If a user decides to exit while in that second script (which is a child process in my mind), how can I tell the parent to exit as well? And can I tell the difference between a user-selected exit versus the script running its course successfully?

2. In each of my Perl/Tk scripts I include a button or a menu option that issues an 'exit' so I can force whatever the script is doing to stop. Works great as long as a user doesn't hit the 'x' in the upper right hand corner of the window. Is there a way to catch that 'x' signal? I've tried creating signal handlers for INT, ABRT, KILL, STOP, and QUIT, but none of them seem to apply.

Any help would be GREATLY appreciated!!

Replies are listed 'Best First'.
Re: Handling child process and close window exits in Perl/Tk
by rcseege (Pilgrim) on Oct 14, 2006 at 17:37 UTC
    The second is standalone because it's general purpose and I didn't want to rewrite it every place I want to use it.

    Points for reuse, but I think your approach has lots of unintended consequences that will require the parent and child to be more complex as a result. You can have the child exit with various codes that your parent can interpret and act accordingly, and that's not really that complex, but will the child be providing other user-supplied information back to the parent? Will the child be around for long time? For example, under your current strategy, your parent will not be able to receive events until the child is done (exits), unless you're using something like fileevent.

    My suggestion would be to create a module out of your reused second window, and treat the second window as a dialog box. for your parent. Your code will be much simpler as a result. Update: (see my followup for examples)

    is there a way to catch that 'x' signal?

    Yes. What you're looking for is something like this:

    use Tk; my $mw = MainWindow->new; $mw->protocol(WM_DELETE_WINDOW => sub { print "Exiting appliction!\n"; exit; }); MainLoop;
    Rob

      Update: did some minor tag/formatting edits

      There are lots of ways to reuse code in modules. My preferred approach when using Tk is to extend existing Tk widgets. I will either extend Frame and create Composites (or megawidgets as they are sometimes called), or I will extend other widgets that do most of what I want.

      Typically, I will also throw most non-gui functionality into other non-tk modules, and I will try to keep the two varieties of modules as separate as possible with no bleedover. I do this to make it easier to test one without the other, and also in case I decide to move to a different kind of GUI at a later time.

      I will even adhere to this separation within a single script if the appliciation is anything more than a trival example or snippet... but that mostly boils down to personal taste on my part, and there are many other approaches you could take. So given your case (and without knowing more details) I might have done something like this:


      Rob
Re: Handling child process and close window exits in Perl/Tk
by zentara (Cardinal) on Oct 14, 2006 at 17:51 UTC
    second Perl/Tk script to get some input from the user. The second is standalone because it's general purpose and I didn't want to rewrite it every place I want to use it.

    Well you sure are "beating your head against the wall" doing it that way. Just spend a few minutes and put the popup code into a module, that you can call from your scripts. That way you can return the user input into local variables. If you need help on how, show us the context you need to get user info, (a small example script), and we can show you a simple popup module.

    For example:

    #!/usr/bin/perl use Tk; my $MainWindow = MainWindow->new; $MainWindow->title("Data Entry Form"); $MainWindow -> Label(-justify => 'left', -text => "Name of person : ") ->pack(-side => 'left',-anchor => 'n'); my $entry = $MainWindow -> Entry(-selectborderwidth => 10) ->pack(-side => 'top',-anchor => 'n'); $entry->bind('<Return>',[\&somesub]); $entry->focus; $MainWindow -> Button(-text => "OK", -command => \&somesub) ->pack(-side => 'bottom',-anchor => 'center'); MainLoop; #your script can continue here after Tk is done while(1){print time; sleep 1;} sub somesub { $,="\n"; $NameOfPerson = $entry -> get; print "\nNameOfPerson ->$NameOfPerson\n"; $MainWindow -> destroy; }
    Is there a way to catch that 'x' signal?

    Yes.

    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = new MainWindow; $mw->title("Close test"); $mw->geometry("400x250"); #prevents mw from closing $mw->protocol('WM_DELETE_WINDOW' => sub { print "do stuff here before the exit\n"; exit; }); MainLoop;

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Handling child process and close window exits in Perl/Tk
by blazar (Canon) on Oct 14, 2006 at 16:57 UTC
    If a user decides to exit while in that second script (which is a child process in my mind), how can I tell the parent to exit as well? And can I tell the difference between a user-selected exit versus the script running its course successfully?

    Programs have an exit status. You can use that as a form of signal. Read perldoc -f system to find out how to find the exit status of the called program. Of course this depends on what the called program does on user exit. For anything more complicated you will need some sort of IPC.

Re: Handling child process and close window exits in Perl/Tk
by meliason (Initiate) on Oct 16, 2006 at 16:56 UTC
    Thanks guys, this is much more help than I expected to get over the weekend. You have NO idea how glad I am to learn about the WM_DELETE_WINDOW protocol...

    As for the child exit, these are all really great examples. I was so focused on the likelihood of this requiring a complex solution that it didn't occur to me to manually define an exit code for the cases I care about within the second script and test after the system() call returns. That seems to be working just fine. Sometimes it's too easy to overlook the fundamentals - thanks for the reminder, blazar!

    Rob - to answer your questions from your first post, the child does not need to provide any information back to the parent other than the exit code. Also, the intended behavior is for the parent to wait for the child to exit before doing anything else. So I *think* in this case system() will be sufficient. But least now I have some excellent examples to go on for the more complex cases.

    Thanks again, everyone -
    Mark