G'day Ppeoc,
The general rule (not one that's written down, as far as I know, but rather something that's served me very well for many years) is to pass a reference to a variable then modify the dereferenced value within the GUI code.
Here's a quick & dirty example (no niceties like titles, geometry, colours, borders, etc.) to demonstrate this:
#!/usr/bin/env perl -l
use strict;
use warnings;
use Tk;
my $mw = MainWindow::->new();
my @choices = qw{A B C D};
my $chosen;
my $tl;
$mw->Button(-text => 'Make Choice', -command => sub {
make_choice(\$mw, \$tl, \@choices, \$chosen);
})->pack();
$mw->Button(-text => 'Show Choice', -command => sub {
if (defined $chosen) {
print "You chose: $chosen";
}
else {
print "Nothing chosen yet!";
}
})->pack();
$mw->Button(-text => 'Exit', -command => sub { exit })->pack();
MainLoop;
sub make_choice {
my ($parent, $tl, $choices, $chosen) = @_;
if (! Exists($$tl)) {
$$tl = $$parent->Toplevel();
my $lb = $$tl->Scrolled('Listbox',
-selectmode => 'single',
-scrollbars => 'osoe',
)->pack();
$lb->insert(end => @$choices);
$$tl->Button(-text => 'Done', -command => sub {
my $selection = $lb->curselection();
if (ref $selection) {
$$chosen = $choices->[$selection->[0]];
}
$$tl->grabRelease();
$$tl->withdraw();
})->pack();
}
else {
$$tl->deiconify();
$$tl->raise();
}
$$tl->grab();
}
Note that the make_choice(...) call only has references as arguments;
accordingly, sub make_choice {...} is totally independent of any global variables.
You could call it with a completely different set of variables and, whatever equates to $chosen in the calling code is modified by $$chosen = ... in &make_choice: there's no need to return $chosen as it's already updated with the new value in the calling code.
As a quick example, clicking on "Show Choice", "Make Choice", "B", "Done", "Show Choice", "Exit" gives this output:
Nothing chosen yet!
You chose: B
Now, I wasn't entirely sure from your description, but I think you want your program to do some non-GUI stuff, then some GUI stuff, then more non-GUI stuff.
I achieved that by keeping &make_choice as is and wrapping nearly everything before it in a subroutine (&run_gui) with these minor changes:
sub run_gui {
my $choice = shift;
...
... sub { $mw->destroy } ... # instead of sub { exit }
...
$$choice = $chosen;
}
And adding a call to run_gui(\$choice); (with a few print statements to indicate what's happening).
Repeating the interaction shown in the earlier "quick example", gives this output:
Do something before GUI.
Hit <Enter> to start GUI:
Nothing chosen yet!
You chose: B
Your choice: B
Do something after GUI.
Here's the new script in its entirety (in the spoiler):
You can probably gain a greater understanding of what's happening here by searching for "closure" in perlref and perlsub.
Also, in case you haven't already seen it, take a look at Tk::callbacks.
|