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

Hey ppl, thanks for always show me some light, after a lot of tries im here to ask for some help with a noob question(i think). My codes bellow make a test using ping, to see if some hosts in a array are alive.
##text Scrolled## $textsc = $txtget->Scrolled ('Text', -scrollbars => 'oe', -width=> 33, -height => 32)->pack; ##Button## my $botaotest = $framebtest -> Button(-text => 'Test Ips!',-command => +\&gotest) -> pack(-side => 'left', -expand => 1,-ipadx => 145); sub gotest{ if ( @$ref){ $textsc->insert('end',"Lets see Wich Ips are ON...\n"); @ipsproxy = map("$_->{ip}", @$ref); $p = Net::Ping->new("icmp"); $p->bind('187.78.223.205 '); @validos = (''); foreach $aaa (@ipsproxy) { print "$aaa is "; unless ($p->ping($aaa, 3)){ print "Host OFF\n"; }else{ push @validos, "$aaa"; printf "ALIVE!!!\n"; sleep(1); } } $p->close(); @nwvalidos = join("\n",@validos); $textsc->insert('end',"Ips Alive:@nwvalidos"); }else{ $textsc->insert('end',"#########ERROR#########\n...I Need Ips to test, + dude!!!"); } }


Whats my problem?
1- When i press Test Buttom, if the array are empty, is shown in my Text Scrolled the msg "#########ERROR#########...I Need Ips...." OK It works! My problem is when i click Test buttom and my array have my ip list, the phrase "Lets see Wich Ips are ON..." is shown only after my ips tests, I need when i clicker in test buttom, the phrase appear first, and then my ip tests start.
>2 - All my ips test results(from foreach command) are being shown in my console, like
"187.115.68.237 is ALIVE!!!
187.44.99.77 is ALIVE!!!
200.131.50.10 is ALIVE!!!
200.198.42.245 is Host OFF
Theres some way to these tests are shown in real time in my Text/Scrolled?

I hope get some help. Thanks guys.

Replies are listed 'Best First'.
Re: TK, insert and foreach
by choroba (Cardinal) on Jun 23, 2011 at 08:45 UTC
    Just use Tk::fileevent.

    Update: or try something like this:

    use File::Tail; use Tk; use warnings; use strict; my $filename = "$ENV{HOME}/.xsession-errors"; my $log = File::Tail::->new(name => $filename, interval => 1, nowait => 1, ); my $mw = MainWindow->new(-title => "Log Watch"); my $t = $mw->Scrolled("Text")->pack; $t->insert("end","== Started at ".localtime); $mw->repeat(1000, sub { my $line = $log->read; $t->insert("end",$line) if defined $line; }); MainLoop;
      Thx for your attention, after your help it worked. I choice use zentara(Bishop) tips because it seemed the easiest solution, taking into account my current level. Thx guys.
Re: TK, insert and foreach
by zentara (Cardinal) on Jun 23, 2011 at 11:20 UTC
    Theres some way to these tests are shown in real time in my Text/Scrolled?

    You have a couple of problems in the way you setup your gotest sub. First, never use a sleep() or an intensive loop in a GUI, it will block the Tk eventloop.

    You probably can make your hack work by printing to the Text widget, instead of the console, and do a $mw->update immediately. Like this:(untested)

    if ( @$ref){ $textsc->insert('end',"Lets see Wich Ips are ON...\n"); @ipsproxy = map("$_->{ip}", @$ref); $p = Net::Ping->new("icmp"); $p->bind('187.78.223.205 '); @validos = (''); foreach $aaa (@ipsproxy) { print "$aaa is "; $textsc->insert('end', "$aaa is "); $mw->update; # etc etc for all your print statements
    But you should redesign your code to account for the fact that Tk has an eventloop. Here are a few examples from previous code posted here.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      Thx for your attention, after your help it worked. I choice use your tip because it seemed the easiest solution, taking into account my current level. Thx guys.
        taking into account my current level.

        Well to help you understand a bit better, whenever you run something that can take time, and/or hang, like a ping, you need to separate that code from the gui eventloop code. This is usually done thru IPC, forking, or threads. That keeps the gui responsive.

        So here is a simpler example of it. This code forks off the ping command, thru a piped open ( see "perldoc perlipc"), and then allows the tk eventloop to read the filehandle thru fileevent ( which is similar to C's select ). The problem with using Net::Ping is that it dosn't allow you direct access to the filehandles involved, like a piped open does. Then you need the hack workaround.

        Here is a simpler version of using fileevent, for you to see the basics.

        #!/usr/bin/perl -w use Tk; use strict; my $host = 'localhost'; my $mw = MainWindow->new; my $t = $mw->Scrolled("Text",-width => 80, -height => 25, -wrap => 'none')->pack(-expand => 1); my $button = $mw->Button(-text => 'Execute', -command => \&ping_test)->pack; MainLoop(); sub ping_test { open (PINGTEST, "ping $host 2>&1 |") or die "can't fork: $!"; $mw->fileevent(\*PINGTEST, 'readable', [\&fill_text_widget,$t]); $button->configure(-text => 'Stop', -command => sub{ print "Close Filehandle\n"; close PINGTEST;# or die "bad ping: $! S?"; print "All done!\n"; }); } sub fill_text_widget { my($widget) = @_; $_ = <PINGTEST>; $widget->insert('end', $_); $widget->yview('end'); }

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh