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

I am using the following code to display a list and get an array of selected entries from user
#!/mu/bin/perl use Tk; use strict; use warnings; my @selections; my @choices = ("choice1", "choice2", "choice3", "choice4", "choice5", +"choice6", "choice7", "choice8"); my $mw = MainWindow->new(-title=>"ListBox"); $mw->Label(-text => 'Select your choices')->pack(); my $lb = $mw->Listbox(-selectmode => 'extended'); $lb->insert('end', sort @choices);$lb->pack(); $mw->Button(-text => 'Select', -command => sub {@selections = $lb->curselection;$m +w->destroy;})->pack(); MainLoop; foreach (@selections) { print $_."\n"; }
This code works fine on its own, after clicking the button, I am able to execute the print statements after MainLoop;. However, when I use this code (without the first 3 lines of course) in a subroutine called in my program, clicking the button only closes the GUI window, anything below the MainLoop; statement is not executed. The whole program just hangs as the subroutine is stuck in the MainLoop. Any suggestion of what I might have done wrong and how can I fix this? Thanks.
  • Comment on Perl Tk unable to return from MainLoop when implemented in a subroutine
  • Download Code

Replies are listed 'Best First'.
Re: Perl Tk unable to return from MainLoop when implemented in a subroutine
by kcott (Archbishop) on Mar 23, 2016 at 12:05 UTC

      Yes I am aware, I actually learnt how to create the GUI from these posts. That is why I do not understand my program hangs after the button click.

        The referenced threads do appear to accomplish what you ask for. However, I consider it a bad idea to mix GUI with command-line interface in the same script. It may confuse your users more than help them. The somewhat non-standard code will be a maintenance problem for the life of your script.
        Bill
Re: Perl Tk unable to return from MainLoop when implemented in a subroutine
by Anonymous Monk on Mar 23, 2016 at 07:57 UTC
    If $mw isnt the only toplevel, mainloop wont end. See tk..wizard/dialog as mainloop not mandatory. Also lookup tkj::exit
      Thanks! This solved my problem. I realised I was having another mainwindow open. Even though the 2 windows do not seem to be related, destroying the other window helped my to proceed with my script flow :)
Re: Perl Tk unable to return from MainLoop when implemented in a subroutine
by kevbot (Vicar) on Mar 23, 2016 at 07:04 UTC

      I'm not sure what you want to see, so below is the code for the whole subroutine I'm writing

      The whole reason I have this subroutine is for user to select some items in the @newSeqUnique array and return the selected array to the calling function

      Currently the code is stuck at the MainLoop; statement

      sub getSelectedSeq { my $newSeqUniqueRef = shift; my $grp = shift; my @newSeqUnique = @$newSeqUniqueRef; my @newSeqUniqueSorted = sort{$a->{ID} cmp $b->{ID} || $a->{folder} cmp $b->{folder}} @newSeqUnique; my @displayedArr; my $displayedStr; my @selectedArr; foreach (@newSeqUniqueSorted) { $displayedStr = $_->{ID}." - ".$_->{folder}; push (@displayedArr, $displayedStr); } select STDOUT; foreach (@displayedArr) { print "$_\n"; } # my $mw = MainWindow->new(-title=>"Select sequences"); my $mw = new MainWindow; $mw->Label(-text => "Below is a list of sequences not found in exi +sting group $grp table")->pack(); $mw->Label(-text => "Please select sequences to be added to new ta +ble")->pack(); my $lb = $mw->Scrolled("Listbox", -scrollbars => "osoe", -height =>10, -width => 30, -selectmode => "extended"); my $real_lb = $lb->Subwidget('scrolled'); $real_lb->configure(-borderwidth=>2); $lb->insert("end", @displayedArr); $lb->pack(-fill=>"both"); $mw->Button(-text => "Select", -command => sub{@selectedArr=$lb->curselection;$m +w->destroy();})->pack(); $lb->selectionSet('end'); $lb->see('end'); MainLoop(); foreach (@selectedArr) { print "$_\n"; } my @arr; my @temp; my ($index, $ID, $folder, $obj); if ((@selectedArr)&&(defined $selectedArr[0])) { foreach (@selectedArr) { push (@arr, $newSeqUniqueSorted[$_]); } }else { @arr = (); } return \@arr; }
        I can't replicate your problem. I added use Tk; to the top of the script, and the following to the bottom:
        print %{ getSelectedSeq([{ ID => 1, folder => '/' }, { ID => 2, folder => 'home' }], 12)->[0] };

        I'm getting the output and the program terminates.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Perl Tk unable to return from MainLoop when implemented in a subroutine (tk modal mainwindow popup deiconify withdraw Show without MainLoop)
by Anonymous Monk on Mar 24, 2016 at 01:39 UTC
    #!/usr/bin/perl -- use strict; use warnings; use Tk qw/ tkinit /; my $mw = tkinit; my $done; my $bu = $mw->Button( -text => "clickme", -command => sub { $done = "I am done " . gmtime; } , )->pack; for( 1 .. 3){ # $mw->deiconify; # $mw->raise; $mw->Popup; $bu->focus; $mw->waitVariable(\$done); ## like mainloop until $done changes print "I am $done again\n"; $mw->withdraw; ## hide, no more mainloop sleep 1; }