Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do you Exit a PERL TK menu via subroutine call? 1

Status
Not open for further replies.

ljsmith91

Programmer
Joined
May 28, 2003
Messages
305
Location
US
I have no doc and I'm struggling to find how its done on any website. I just want to exit out of the a perl/tk menu that I create in a separate subroutine. The EXIT Action Button works to exit the menu but the SUBMIT Action button does not. I would like to exit the menu at the end of the get_input subroutine. Here's the excerpt from the script:

Code:
my $main = MainWindow->new();
$Action_Submit 	= $main->Button(-text => 'Submit', -command => [\&get_input ])->place(-x => 700, -y => 45);

$Action_Exit	= $main->Button(-text => 'Exit', -command => [$main => 'destroy'])->place(-x => 700, -y => 115);

# This menu has several radio and action buttons. Once 
# filled out, I want to first pull all of the data input 
# into the menu and place them into variables....then exit. # However, this does not Exit the menu as i would think it 
# should. Instead the menu stays active until we actually 
# exit the script.

sub get_input {
    $ftp_loginid	= $LoginID->get;
    $ftp_pw 	        = $LoginPW->get;
    $ftp_localdir 	= $LocalDIR->get;
    $main => destroy;
}

Is there a valid way of exiting the menu ? "$main => destroy;" fails to do so. Thanks.


 
One option:
Code:
[code]
-command => sub { killwin()}; 




sub killwin
{
 $main->DESTROY if Tk::Exists($main);
 exit;

}




dmazzini
GSM System and Telecomm Consultant

 
Thanks dmazzini,

Unfortunately, that doesn't work for me. I want to exit the $main Menu without exiting the script. I basically pull all the info the user input into the menu, now I want to go and do what the user asked and allow him to follow along with logging info in a command window. So I want to exit Out of the $main menu. For me, it ONLY exits out of $main when I issue a perl "exit". I have not found the way of simply exiting the menu and continuing on with the script. Seems simple but I havent discovered how. Any ideas?


 
Your problem is with your -command calls.

-command only requires an array reference if you're both specifying a subroutine (or coderef), AND passing certain variables into it. For example:

Code:
$mw->Button (
   -text => 'click me',
   -command => [
      \&handler,
      'some argument',
      'another argument',
   ],
)->pack;

sub handler {
   my ($button,$arg1,$arg2) = @_;

   print "$arg1\n$arg2\n";
   # prints:
   # some argument
   # another argument
}

That being said, in your command with $main=>destroy, you're specifying a "fake" coderef ($main) as a subroutine to handle it, which probably causes errors, and passing "destroy" as an argument (which is probably causing warnings because destroy probably hasn't been defined as a constant).

Here's the proper usage for your exit button:
Code:
$Action_Exit    = $main->Button(-text => 'Exit', -command => sub { $main->destroy; })->place(-x => 700, -y => 115);

If you notice, I used an anonymous subroutine rather than a reference to one, like you have on your submit button. To go back to the previous example:

Code:
$mw->Button (
   -text => 'click me',
   -command => [
      sub {
         my ($button,$arg1,$arg2) = @_;

         print "$arg1\n$arg2\n";
         # prints:
         # some argument
         # another argument
      },
      'some argument',
      'another argument',
   ],
)->pack;

Use arrayrefs as -command's value when you want to pass arguments into the subroutine, otherwise -command => \&sub works just fine.
 
Another thing I should add:

destroy is a method of $main, so you use a -> style arrow to call it (the => type of arrow is generally only used when defining associative array keys with their values).

Code:
$main->destroy;

Put that in your sub get_input too where you had it the other way around.
 
Kirlse,

Thanks...I guess I am still not getting it. I recognize that I was using the wrong arrow "=>" instead of "->" and that was a clear mistake. However, in your "$mw->Button " example above, you never exit the dialog or menu and that is what my objective is. I understand what you say about passing args to the called subroutine. I simply want to call whatever subroutine, insure I have my args set whether they were passed or set in the subroutine, then Exit the main dialog or menu and then continue on with the script utilizing the args set/retrieved. I still cannot glean from your reply how the menu is closed and the script continues to execute. Thanks so much for your help.
 
Is the code you posted above the full source to your code? If you post the full code (including the radio buttons and everything) it will help us help you.

But here's a blind shot in the dark for me:

Code:
my $main = MainWindow->new;

$main->Label (-text => 'Login ID:')->pack;
our $LoginID = $main->Entry->pack;

$main->Label (-text => 'Password:')->pack;
our $LoginPW = $main->Entry->pack;

$main->Label (-text => 'Directory:')->pack;
our $LocalDIR = $main->Entry->pack;

our $Action_Submit = $main->Button (
   -text => 'Submit',
   -command => \&get_input,
)->pack;

our $Action_Exit = $main->Button (
   -text => 'Edit',
   -command => sub {
      $main->destroy;
   },
)->pack;

MainLoop;

sub get_input {
   our $ftp_loginid = $LoginID->get;
   our $ftp_pw      = $LoginPW->get;
   our $ftp_localdir = $LocalDIR->get;
   $main->destroy;
}

Now that I think about it, if this was the full source of a code that I just posted, the Perl script would end at the same time that $main was destroyed. The reason is that MainLoop goes on a loop to update the GUI elements. When there are no Tk elements left to update (because you killed the MainWindow and all its widgets), MainLoop will return false, allowing the script to continue through its code. If there's nothing below MainLoop to do anything, it will simply end the script and everything will be done.
 
Kirlse,

The code example you provide above is almost exactly as I have it coded, the one difference is that after the $main->detroy statement in the "get_input" subroutine, I proceed to do a number of different things(another 20 lines of code) including printing out to STDOUT what is going on. The $main window never gets destroyed, it stays active in the foreground and the invoker never gets an indication of what happens. The Submit button remains in a depressed state on this main menu until the get_input subroutine completes its execution(takes a few minutes). At that point the SUbmit button is undepressed(available again) and the Exit button can be pressed allowing the script to end.

I want the menu to bail out right after the Submit button is pressed although this appears to not be doable as even though its a separate subroutine it called within the MainLoop subroutine and therefore MainLoop is keeping it Active.

Is there a way of exiting out of the main menu once the Submit button is depressed ? I am starting to think not but I am hopeful there is something I am not yet aware of out there.
 
Kirlse,

Try adding a "sleep 30;" after your $main-> destroy; statement in the get_input subroutine....the Main window will not close until the get_input subroutine finishes sleeping. Maybe this helps to pinpoint my issue.

Thanks.
 
I dunno. I just turned what I last posted into runnable code to test, and put the sleep 30 in the subroutine. For me, the window still disappeared immediately, followed by a 30 second wait, followed by printing to STDOUT what the variables were.

Code:
use Tk;

my $main = MainWindow->new;

$main->Label (-text => 'Login ID:')->pack;
our $LoginID = $main->Entry->pack;

$main->Label (-text => 'Password:')->pack;
our $LoginPW = $main->Entry->pack;

$main->Label (-text => 'Directory:')->pack;
our $LocalDIR = $main->Entry->pack;

our $Action_Submit = $main->Button (
   -text => 'Submit',
   -command => \&get_input,
)->pack;

our $Action_Exit = $main->Button (
   -text => 'Exit',
   -command => sub {
      $main->destroy;
   },
)->pack;

MainLoop;

sub get_input {
   our $ftp_loginid = $LoginID->get;
   our $ftp_pw      = $LoginPW->get;
   our $ftp_localdir = $LocalDIR->get;
   $main->destroy;
   sleep 30;
}

print "loginid: $ftp_loginid\n"
	. "pw: $ftp_pw\n"
	. "localdir: $ftp_localdir\n";
 
Kirlse,

Thanks for your help and time on all this. I was away all day today. I hope to take a closer look at this tomorrow and find where I went wrong as its not jumping out at me.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top