Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Solution Failure #1

by cmv (Chaplain)
on Dec 18, 2009 at 19:54 UTC ( #813425=note: print w/ replies, xml ) Need Help??


in reply to Tk Dialog From Multiple POE Processes?

zentara++
rcaputo++
Thanks for the good advice!

If I understand my options correctly, I have 2 choices:

  • Funnel all child GUI requests through the parent
  • Setup new Tk mainloops for each child

    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); }


  • Comment on Solution Failure #1
    Download Code

    Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Node Status?
    node history
    Node Type: note [id://813425]
    help
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others contemplating the Monastery: (7)
    As of 2014-12-26 20:57 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      Is guessing a good strategy for surviving in the IT business?





      Results (176 votes), past polls