in reply to Tk Dialog From Multiple POE Processes?
If I understand my options correctly, I have 2 choices:
My first attempt is trying to funnel all the child GUI requests through the parent (since I don't know how to startup new Tk mainloops for the children), but I'm having problems.
I thought to create an event handler (KidAsk) in the parent, that would do the GUI request and return the result (see code below). Uncommenting the line labeled "Verification" verifies that the event handler works (when called from the parent).
My problem seems to be how to get this event handler to fire from the child? I first tried the commented out line labeled "Question 1", but that doesn't work (I'm guessing because the child process can't fire an event in the parent?). Next I tried creating a new event (AskEvent) for the child, and mapping that to the parent's event (KidAsk) in the same way that StdoutEvent & friends are mapped (see lines labeled "Question 2"). Apparently adding new events isn't allowed in POE::Wheel::Run, as this fires a warning message.
So, what is the best way to do this? Am I anywhere near close?
Thanks
-Craig
use strict; use warnings; use Data::Dumper; # The "use Tk" MUST be before "use POE"... use Tk; use Tk::DialogBox; use POE; use POE::Wheel::Run; # Create GUI window... my $top = $::poe_main_window; $top->geometry('300x50'); $top->title("PID=$$"); $top->protocol('WM_DELETE_WINDOW', sub{exit}); # Create button to push... $top->Button(-text=>"Don't Push Me - WAIT", -command=>sub{ print STDERR "Parent Asking User\n"; print STDERR "Got: ", AskUser("PID=$$"), "\n"; })->pack; print STDERR "Parent PID=$$\n"; my $session=_poeSetup(); # Go... $poe_kernel->run(); sub _poeSetup { my $session = POE::Session->create( inline_states=>{ KidAsk => sub { print STDERR "GUI Request from Child...\n"; my $ret=AskUser("PID=$$"); print STDERR "Got: $ret\n"; return($ret); }, KidOut => sub { my ($heap, $line, $wid)=@_[HEAP, ARG0, ARG1]; my $child = $heap->{Kids}{WID}{$wid}; print STDERR $child->PID . " OUT: $line\n"; }, KidErr => sub { my ($heap, $line, $wid)=@_[HEAP, ARG0, ARG1]; my $child = $heap->{Kids}{WID}{$wid}; print STDERR $child->PID . " ERR: $line\n"; }, KidClose => \&_DoClose, _start => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; $kernel->alias_set('GUI'); my $child = POE::Wheel::Run->new( Program => sub { print STDERR "Sleeping..."; system("sleep 3"); print STDERR "GUI Request from $$\n"; # Question 1 my $ret = $kernel->post('GUI','KidAsk'); # Question 2 my $ret = $kernel->yield('AskEvent'); print STDERR "DONE: $ret\n"; system("tail -f /etc/profile"); }, StdoutEvent => 'KidOut', StderrEvent => 'KidErr', CloseEvent => 'KidClose', # Question 2 AskEvent => 'KidAsk', ); $kernel->sig_child($child->PID, '_DoSig'); $heap->{Kids}{WID}{$child->ID} = $child; $heap->{Kids}{PID}{$child->PID} = $child; # Verification $kernel->yield('KidAsk'); } }, ); return($session); } ################################# # POE Session Supporting Routines ################################# sub _DoClose { my $wid = $_[ARG0]; my $child = $_[HEAP]{Kids}{WID}{$wid}; unless (defined $child) { print STDERR "wid $wid closed all pipes.\n"; return; } print STDERR "wid $wid closed all pipes.\n"; delete $_[HEAP]{Kids}{PID}{$child->PID}; } sub _DoSig { print STDERR "pid $_[ARG1] exited with status $_[ARG2].\n"; my $child = delete $_[HEAP]{Kids}{PID}{$_[ARG1]}; return unless defined $child; delete $_[HEAP]{Kids}{WID}{$child->ID}; } sub AskUser { my $txt = shift || 'No text passed'; print STDERR "$txt\n"; my $top = $::poe_main_window; # Create a dialog box to ask for a password... my $d = $top->DialogBox( -title=>"$txt", -buttons=>['Ok', 'Cancel'], -default_button=>'Ok', ); # Add the entry widget where user will type password... my $e = $d->add('Entry', -width=>30, -show => '*')->pack; $d->add('Label', -text => "What is your favorite color?")->pack; my $ans = $d->Show(); # If user didn't say ok... if ($ans ne "Ok") { die( "I give up, exiting...\n") }; # Get & return what the user typed... my $pw = $e->get; return($pw); }
|
|---|