Re: Perl/Tk and exit(0)
by kcott (Archbishop) on Apr 03, 2020 at 08:03 UTC
|
G'day saw55,
Welcome to the Monastery.
I see the reason for your problem has been explained by ++jcb.
Instead of calling exit(0) as you currently do,
consider passing a flag that instructs &timedDialog to either
destroy the dialogue or exit the application.
Here's a fully functional, albeit extremely barebones, example of what I mean.
#!/usr/bin/env perl
use strict;
use warnings;
use Tk;
{
my $mw = MainWindow::->new();
$mw->Button(
-text => 'Transient message',
-command => sub { out_msg(\$mw, 'Message ...', 2_000) },
)->pack();
$mw->Button(
-text => 'No backup',
-command => sub { out_msg(\$mw, 'Exiting ...', 2_000, 1) },
)->pack();
}
sub out_msg {
my ($mw_ref, $msg, $delay, $exit) = @_;
my $tl = $$mw_ref->Toplevel();
$tl->Label(-textvariable => \$msg)->pack();
my $handle_msg = $exit
? sub { exit }
: sub { $tl->destroy };
$tl->after($delay, $handle_msg);
}
MainLoop;
Note that the flag is only needed for those callbacks where you want to exit:
you may only need to make minimal changes if you adopt this technique.
Here's a few other points that aren't directly related to your current problem:
-
Avoid referencing external variables in your subroutines; pass them in as arguments.
Prefer references to variables rather than the variable's value;
this will avoid unexpected bugs, that are often hard to track down, in your Tk scripts.
I've shown \$mw and $mw_ref in my code as an example;
admittedly, this was somewhat contrived but there were few opportunities for examples
in such a short script — it's still a valid example and, if you run that code,
you'll see it works without any problems.
-
You might also note that $mw does not have file scope.
It is constrained to an anonymous block and completely inaccessible by &out_msg.
-
Prefer calling subroutines without a leading ampersand; i.e. subname() in favour of &subname.
The &subname and &subname(@arg_list) forms are generally not what you want and can lead to problems.
See perlsub for details.
-
Probably more for future reference: there are many dialogue and messaging widgets
that are part of the core Tk distribution.
See the Popups and Dialogs section of the Tk documentation.
| [reply] [d/l] [select] |
|
|
Thanks you so much, and thanks to jcb as well. As I am sure you you can tell, I am new to Tk, but this gives me something to work with. I knew there were standard popups available--I use them elsewhere in the program--but I think I couldn't figure out how to close them programatically.
| [reply] |
|
|
| [reply] [d/l] |
Re: Perl/Tk and exit(0)
by tybalt89 (Monsignor) on Apr 03, 2020 at 01:24 UTC
|
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11114965
use warnings;
use Tk;
my $mw = MainWindow -> new;
$mw->geometry( '+600+400' );
my $timedDialogTitle = '';
my $timedDialogText = '';
my $svBtn = undef; #Option window SAVE button.
&setupGUI;
#$mw->deiconify();
#$mw->raise();
MainLoop;
#exit(0);
################################################
################################################
sub setupGUI{
$timedDialogTitle = "STARTING BACKUP";
$timedDialogText = "Backing up files...";
$svBtn = $mw->Button( -text => "SAVE",
-command => sub {&checkDays;
# exit(0);
});
$svBtn->grid(-row => 9, -column => 2, -sticky => 'e');
$mw->bind('<KeyPress-Return>' => sub {checkDays();
# exit(0);
});
# $mw-> withdraw();
}
#####################################
sub checkDays
{
timedDialog("Exiting",
"O.K., no backup will be made, then....Exiting",
2_000);
}
#####################################
sub timedDialog
{
print ("in timedDialog\n");
# my $subwindow = MainWindow->new;
my $subwindow = $mw->Toplevel;
$subwindow->geometry("490x150+400+400");
$subwindow->title($_[0]);
my $label = $subwindow->Label(-text => $_[1]);
$label->pack;
$subwindow->after($_[2], sub {$subwindow->destroy;});
print ("after timedDialog\n");
}
#####################################
| [reply] [d/l] |
Re: Perl/Tk and exit(0)
by 1nickt (Canon) on Apr 02, 2020 at 23:15 UTC
|
Hi, I am not a Tk programmer, but ... exit exits :-) If you want to return from a sub, return :-)
(And commenting out the exit statement makes your script work because you don't need to use an explicit return statement to return from a sub, if you are not returning anything.)
Hope this helps!
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
|
G'day 1nickt,
The link you posted labeled "exit" is to a Google search
(http://www.google.com/search?q=exit%20site%3Aperldoc.perl.org).
The first item returned from that search is to perldoc (https://perldoc.perl.org/functions/exit.html).
I couldn't see anything else pertinent, so I'm wondering why the intermediary Google step.
Anyway, the point is somewhat moot as that's the wrong "exit".
"I am not a Tk programmer ..."
In my experience, even amongst Tk programmers, it's a little known fact that
Tk exports, by default, its own exit:
Tk::exit.
Knowing that doesn't help the OP but I thought it was worth mentioning.
| [reply] [d/l] |
|
|
Thanks Ken, I'll update the link. Not sure how that happened.
Update: I fixed the links by changing from [perldoc:// to [doc://. I wonder if the behaviour of the former syntax is new, broken, or something I just imagined was different. The links as I originally posted definitely went to a Goog search. Maybe a topic for PM Discussion...
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
|
|
|
|
|
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
Thanks for the reply. I know exit causes the program to exit, but I believe the call to the subroutine preceding the exit statement should cause the message window to display before the program exits. I know sub timedDialog executes because I inserted a print statement in it and it does indeed print but the message window never displays; and I put a sleep statement between the sub call and exit in hope of allowing time for the message to display but no go.
I just noticed I called timedDialog both in sub checkDays and in sub setupGUI I fixed this and still no message shows
Fixed code follows
#!/usr/bin/perl
######################################################################
+##
use strict;
use warnings;
use Tk;
my $mw = MainWindow -> new;
my $timedDialogTitle = '';
my $timedDialogText = '';
my $svBtn = undef; #Option window SAVE button.
&setupGUI;
$mw->deiconify();
$mw->raise();
MainLoop;
exit(0);
################################################
################################################
sub setupGUI{
$svBtn = $mw->Button( -text => "SAVE", -command => sub {&checkDays
+; exit(0);});
$svBtn->grid(-row => 9, -column => 2, -sticky => 'e');
$mw->bind('<KeyPress-Return>' => sub {&checkDays; exit(0);});
$mw-> withdraw();
}
#####################################
sub checkDays {
&timedDialog("Exiting", "O.K., no backup will be made,
+ then....Exiting", 25_000);
sleep 15;
}
#####################################
sub timedDialog
{
print ("in timedDialog\n");
my $subwindow = MainWindow->new;
$subwindow->geometry("490x150+400+400");
$subwindow->title($_[0]);
my $label = $subwindow->Label(-text => $_[1]);
$label->pack;
$subwindow->after($_[2], sub {$subwindow->destroy;});
}
#####################################
| [reply] [d/l] |
|
|
| [reply] [d/l] |
|
|
|
|
|
Re: Perl/Tk and exit(0)
by Anonymous Monk on Apr 03, 2020 at 12:46 UTC
|
Especially if the program is about to exit anyway, you can insert another call to the event-loop handler so that the event queue is run through one more time. The drawing never happens because the event is queued but never processed. | [reply] |