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

The following works the way I want it to if I use “$mw→destroy;” to get rid of the main window when I am done with it. But when I try to use $mw-> withdraw(), the program doesn’t show all the dialogs and hangs—it doesn’t finish unless I hit ctrl-c. Can someone tell me what I am doing wrong?

This works:

#!/usr/bin/perl # Demo new "MainWindow" vs. "withdraw " problem. use Tk; use strict; use warnings; use Tk::DialogBox; require Tk::Dialog; my $mw = MainWindow -> new; my $fontHelv = 'Helvetica 12'; $mw->optionAdd('*font', $fontHelv); my $timedDialogText = ''; my $dest = ''; my $answer = ''; my $renameString; my $excludeFile; my $scriptDir = "FILE"; $timedDialogText = &mainGUI($timedDialogText); $renameString = &timeSinceLastRun; $mw->deiconify(); $mw->raise(); # Show the mainwindow MainLoop; &printRenameMessage($timedDialogText, $dest, $renameString); &exitingPopup($renameString); exit(0); sub mainGUI{ my $timedDialogText; my $svBtn = undef; # SAVE button. my $timedDialogTitle = ''; $svBtn = $mw->Button( -text => "SAVE", -command => sub { keyPressM +ainGUI($dest, $timedDialogText) + } ); $svBtn->grid(-row => 9, -column => 2, -sticky => 'e'); $mw->bind('<KeyPress-Return>' => sub { keyPressMainGUI($dest, $ti +medDialogText) + } ); $mw-> withdraw(); # return "timedDialogText"; } sub keyPressMainGUI{ my $dest = $_[0]; my $timedDialogText = $_[1]; $mw->destroy();; #### #$mw->withdraw();; #### $timedDialogText = &timedDialog("timedDialogTitle", "timedDialogTe +xt", 2_000); } sub QuestionDialogBox{ my $renameString = ("[0]\n"); $mw->withdraw; #### $answer = $mw->Dialog(-title => $_[0], -text => $_[1], -default_button => 'Finish', -buttons => ['Finish'], -bitmap +=> 'info' )->Show(-global, -popover => $mw, -overanchor => 'c', -popanchor => 'c' ); $mw->geometry("450x150+10+10"); return "answer"; } sub printRenameMessage { $mw = MainWindow -> new; #### $answer = &QuestionDialogBox( "Create Archives?", "Do you want + to save the files in a tarball named renameString?"); &timedDialog("Progress", "timedDialogText", 5_000); &timedDialog("COMPLETE", "timedDialogTextX\n\nCreating fie Dat +e...X\n\nFinished.", 5_000); } sub timeSinceLastRun{ my $answer = &QuestionDialogBox( "Do you want to continue?"); return "renameString"; } sub exitingPopup { my $renameString = $_[0]; my $visibleStr = ''; $answer = $mw->Dialog(-title => "COMPLETE", -text => "visibleStr \n excludeStr", -default_button => 'Finis +h', -buttons => ['Finish'], -bitmap => 'info' )->Show(-global, -popover => $mw, -overancho +r => 'c', -popanchor => 'c' ); $mw->geometry("450x150+10+10"); } sub timedDialog { my $subwindow = MainWindow->new; $subwindow->optionAdd('*font', $fontHelv); $subwindow->geometry("490x150+400+400"); $subwindow->title($_[0]); my $label = $subwindow->Label(-text => $_[1]); $label->pack; $subwindow->after($_[2], sub {$subwindow->destroy;}); }

This doesn’t work:

#!/usr/bin/perl # Demo new "MainWindow" vs. "withdraw " problem. use Tk; use strict; use warnings; use Tk::DialogBox; require Tk::Dialog; my $mw = MainWindow -> new; my $fontHelv = 'Helvetica 12'; $mw->optionAdd('*font', $fontHelv); my $timedDialogText = ''; my $dest = ''; my $answer = ''; my $renameString; my $excludeFile; my $scriptDir = "FILE"; $timedDialogText = &mainGUI($timedDialogText); $renameString = &timeSinceLastRun; $mw->deiconify(); $mw->raise(); # Show the mainwindow MainLoop; &printRenameMessage($timedDialogText, $dest, $renameString); &exitingPopup($renameString); exit(0); sub mainGUI{ my $timedDialogText; my $svBtn = undef; # SAVE button. my $timedDialogTitle = ''; $svBtn = $mw->Button( -text => "SAVE", -command => sub { keyPressM +ainGUI($dest, $timedDialogText) + } ); $svBtn->grid(-row => 9, -column => 2, -sticky => 'e'); $mw->bind('<KeyPress-Return>' => sub { keyPressMainGUI($dest, $ti +medDialogText) + } ); #$mw-> withdraw(); # Uncomment return "timedDialogText"; } sub keyPressMainGUI{ my $dest = $_[0]; my $timedDialogText = $_[1]; $mw->withdraw; #### Switch these 2 #$mw->destroy; #### $timedDialogText = &timedDialog("timedDialogTitle", "timedDialogTe +xt", 2_000); } sub QuestionDialogBox{ my $renameString = ("[0]\n"); $mw->raise; #$mw->withdraw; #### Uncomment $answer = $mw->Dialog(-title => $_[0], -text => $_[1], -default_button => 'Finish', -buttons => ['Finish'], -bitmap +=> 'info' )->Show(-global, -popover => $mw, -overanchor => 'c', -popanchor => 'c' ); $mw->geometry("450x150+10+10"); return "answer"; } sub printRenameMessage { #$mw = MainWindow -> new; #### Uncomment $answer = &QuestionDialogBox( "Create Archives?", "Do you want + to save the files in a tarball named renameString?"); &timedDialog("Progress", "timedDialogText", 5_000); &timedDialog("COMPLETE", "timedDialogTextX\n\nCreating fie Dat +e...X\n\nFinished.", 5_000); } sub timeSinceLastRun{ my $answer = &QuestionDialogBox( "Do you want to continue?"); return "renameString"; } sub exitingPopup { my $renameString = $_[0]; my $visibleStr = ''; $answer = $mw->Dialog(-title => "COMPLETE", -text => "visibleStr \n excludeStr", -default_button => 'Finis +h', -buttons => ['Finish'], -bitmap => 'info' )->Show(-global, -popover => $mw, -overancho +r => 'c', -popanchor => 'c' ); $mw->geometry("450x150+10+10"); } sub timedDialog { my $subwindow = MainWindow->new; $subwindow->optionAdd('*font', $fontHelv); $subwindow->geometry("490x150+400+400"); $subwindow->title($_[0]); my $label = $subwindow->Label(-text => $_[1]); $label->pack; $subwindow->after($_[2], sub {$subwindow->destroy;}); }

Any help would be appreciated,

Replies are listed 'Best First'.
Re: PERL / Tk MainWindow -> new and destroy(), vs. $mw-> withdraw() and raise().
by jcb (Parson) on Apr 13, 2020 at 02:38 UTC

    The Tk MainLoop returns when all MainWindows are destroyed. If you want to be able to merely withdraw the MainWindow, you will need to move the effects of lines 27 and 28 into Tk callback handlers. The program is hanging when the MainWindow is withdrawn because it reaches a state where no GUI elements are present, but Tk is still waiting for events — deadlock!

      As you suggested I moved those subroutine calls to the end of my keyPressMainGUI handler and now everything works fine. Thanks so much!