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

Hello Monks,

I have one problem.

I was did a program to be a interface between a chat to desktop, to send and received messages but out of browser.

It's okay to received or send messages if the routines are separate in two programs, but to join both on a one program need some mechanism to manipulate both routines, because the shell (on Windows or Linux) can't receive and send in same time.

To do it I make an interface with Tk, but to receive message have some problem, when Tk make a Loop it receive only one message, to receive next I need to kill just a interface, or restart the program.

In fact, I really didn't know to use the Tk, I'm trying to two weeks but I could not, if someone can help me.

Here's the code:

#!usr/bin/env perl use Tk; use common::sense; use WWW::Mechanize; use WWW::Mechanize::DecodedContent; use JSON -support_by_pp; use HTTP::Cookies; use URI::Escape; my $mw = new MainWindow(-background => 'blue'); $mw->geometry("600x400"); $mw->minsize(qw(400 650)); $mw->maxsize(qw(800 750)); $mw->title("Invaders External ShoutBox"); my $getmsg = $mw -> Frame(-background => 'red', -relief=>'raised', -borderwidth=>1, ) ->place(-x =>70, -y =>25); my $gmsg = $getmsg->Scrolled ('Text', -width=> 60, -height => 20, -background => 'black', -foreg +round => 'green')->pack; $gmsg->insert('end',"Start External ShoutBox...\nInVaDeRs\n"); my $putmsg = $mw -> Frame(-background => 'red', -relief=>'raised', -borderwidth=>1, ) ->place(-x => 70, -y => 450); my $pmsg = $putmsg->Scrolled ('Text', -width=> 60, -height => 5, -background => 'black', -foregr +ound => 'green')->pack; $pmsg->insert('end',"..."); my $url = WWW::Mechanize->new(); $url->get("http://www.forum-invaders.com.br/vb/login.php"); $url->submit_form( fields => { vb_login_username => 'login', vb_login_password => 'password', } ); if($url->decoded_content !~ /Bem-vindo/gi){$gmsg->insert('end', "L +oggin Error\n");} else {$gmsg->insert('end', "Login OK!\n");} my $work = 1; my @old; my $num = 0; while ($work == 1){ my $r = $url->get("http://www.forum-invaders.com.br/vb/vbshout +.php?type=activeusers&do=ajax&action=fetch&instanceid=2"); my $json = JSON->new->relaxed; my $s = $json->decode($r->decoded_content); my $msg = $s->{"shouts"}->{0}->{"message_raw"}; my $user = $s->{"shouts"}->{0}->{"musername"}; my $name; if ($user =~ />(.+)<\/span/gi) {$name = $1;} else {$name = $user} my $now = join(" => ", $name, $msg) . "\n"; if ($num == 0){ $gmsg->insert('end', $now); push (@old, $now); $num++; } elsif($old[$num - 1] ne $now){ $gmsg->insert('end', $now); push (@old, $now); $num++; } } MainLoop;

Replies are listed 'Best First'.
Re: [HELP] Chat, two routines, Tk
by zentara (Cardinal) on Jul 01, 2012 at 17:48 UTC
    Hi, just by looking at the code itself, it almost looks like you could get the Mechanize network code to co-exist with Tk for multiple updates. It probably would be best to put your Mechanize code into a separate thread, but with Tk, you cannot update a Tk widget from the thread. If you wanted to use Gtk2 instead of Tk, you CAN update a Gtk2 widget from a thread.

    But lets just look at Tk. If you put your whole Mechanize sub into a thread, and run it from a timer or button press, you will need to find a way thru shared variables or a shared fileno to get the results from the thread, and update your Tk Text widget. See Re: Perl/Tk threading and/or cron job? for a simple demonstration of how to do it.

    If you just want to hack around, just to get where you can have multiple runs of the Mechanize sub, just put the Mechanize code into a Button callback, and sprinkle it with $mw->update, so as not to unduely block the responsiveness of the Tk eventloop.

    I havn't tested the following, and I emphasize you are better off putting the Mechanize code into a thread, but this will help you get multiple runs going. You also will probably need to work out a scheme for disabling the Button by setting it's state=>disabled after each button press, and return to state=>normal after Mechanize is done. This is to prevent you from running it twice in rapid succession. You will also probably notice that while Mechanize is running, the Tk window may become unresponsive, that is why there are a bunch of $mw->update lines in there. In a thread based solution, you wouldn't need those lines. So look closely at Re: Perl/Tk threading and/or cron job? and you should be able to move the network code into a thread.

    #!/usr/bin/perl use warnings; use strict; use Tk; use common::sense; use WWW::Mechanize; use WWW::Mechanize::DecodedContent; use JSON -support_by_pp; use HTTP::Cookies; use URI::Escape; my $mw = new MainWindow(-background => 'blue'); $mw->geometry("600x400"); $mw->minsize(qw(400 650)); $mw->maxsize(qw(800 750)); $mw->title("Invaders External ShoutBox"); my $getmsg = $mw -> Frame(-background => 'red', -relief=>'raised', -borderwidth=>1, ) ->place(-x =>70, -y =>25); my $gmsg = $getmsg->Scrolled ('Text', -width=> 60, -height => 20, -background => 'black', -foreg +round => 'green')->pack; $gmsg->insert('end',"Start External ShoutBox...\nInVaDeRs\n"); my $putmsg = $mw -> Frame(-background => 'red', -relief=>'raised', -borderwidth=>1, ) ->place(-x => 70, -y => 450); my $pmsg = $putmsg->Scrolled ('Text', -width=> 60, -height => 5, -background => 'black', -foregr +ound => 'green')->pack; $pmsg->insert('end',"..."); my $button = $mw->Button( -text => 'Update', -command => \&update_me)->pack(); MainLoop; sub update_me{ my $url = WWW::Mechanize->new(); $url->get("http://www.forum-invaders.com.br/vb/login.php"); $mw->update(); $url->submit_form( fields => { vb_login_username => 'login', vb_login_password => 'password', } ); if($url->decoded_content !~ /Bem-vindo/gi){$gmsg->insert('end', "L +oggin Error\n");} else {$gmsg->insert('end', "Login OK!\n");} my $work = 1; my @old; my $num = 0; while ($work == 1){ my $r = $url->get("http://www.forum-invaders.com.br/vb/vbshout +.php?type=activeusers&do=ajax&action=fetch&instanceid=2"); my $json = JSON->new->relaxed; my $s = $json->decode($r->decoded_content); my $msg = $s->{"shouts"}->{0}->{"message_raw"}; my $user = $s->{"shouts"}->{0}->{"musername"}; my $name; $mw->update(); if ($user =~ />(.+)<\/span/gi) {$name = $1;} else {$name = $user} my $now = join(" => ", $name, $msg) . "\n"; if ($num == 0){ $gmsg->insert('end', $now); $mw->update(); push (@old, $now); $num++; } elsif($old[$num - 1] ne $now){ $gmsg->insert('end', $now); push (@old, $now); $num++; } $mw->update(); } $mw->update(); }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: [HELP] Chat, two routines, Tk
by Anonymous Monk on Jul 01, 2012 at 16:12 UTC