2011-09-29 3 views
0

J'ai une petite application Perl Tk avec une fenêtre de texte que je veux être mise à jour de manière non tamponnée comme je l'ai avec mes fichiers journaux, mais je ne peux pas le faire fonctionner à cause de ma mauvaise compréhension de tout ce qui concerne Perl.Perl Tk: confusion avec la mise à jour d'une fenêtre de texte

L'application lit un index XML, l'analyse puis charge chaque ID trouvé dans le fichier XML en tant qu'URL pour mettre en cache la page. Ceux-ci peuvent être numérotés de 1700 à 19 000 selon le $ pubId entré et prend quelques heures.

Je le code suivant pour le bouton Submit et la fenêtre de texte:

my $submit_image = $pict->Photo(-file => $submit); 
    my $submit_button = $mw->Button(
    -image => $submit_image, 
    -text => "Submit", 
    -background => "#cccccc", 
    -command => sub { 

     if ($pubId eq '') { 
      $|; 
    Log_message ("\n$DATE - $TIME - WARNING: Please complete all fields\t"); 
    tk_message ("Please enter a valid Publication ID"); 
} 
else { 
    request_url(); #Open the xml url and read it in 
    } 
    $text->insert( 
       # put something to the _end_ of the text 
       # which is in the widget 
       'end', 
       sprintf(" $txtmesg\n") 
      ); 
      # Set window to the end of the text 
      # I want to see the newest events immediately 
      $text->see('end'); 
     }) ->place(-x => 60, -y =>195); 

qui fonctionne si le bouton est pressé avec un pubId $ vide ou invalide (request_url fait un contrôle supplémentaire pour voir si le code html body contient le mot 404 et des erreurs sur un message à la fenêtre).

Mais si tout va bien et que request_url() s'exécute, alors toute la fenêtre Tk se fige et je ne peux pas utiliser mon bouton de sortie et je dois le fermer via l'invite de commande.

Je sais que je devrais faire ceci différemment mais jusqu'ici chaque site que j'ai regardé est trop compliqué pour moi et je m'étonne juste. Je suis à la recherche de quelques instructions noddy pour me permettre de travailler à travers cela.

Merci.

EDIT: J'ai maintenant essayé d'utiliser MainLoop(); et le DoOneEvent(): dans mon sub mais je vois toujours le même gel de gui et aucune mise à jour de fenêtre.

Je continuerai à faire des recherches et des expériences.

-command => \&long_job) 

MainLoop(); 

    sub long_job { 
     if ($pubId eq '') { 
      $|; 
    Log_message ("\n$DATE - $TIME - WARNING: Please complete all fields\t"); 
    tk_message ("Please enter a valid Publication ID"); 
} 
else { 
    DoOneEvent(); 
    request_url(); #Open the xml url and read it in 
    } 
    } 
+0

On dirait que le problème est que 'request_url' fonctionne de manière synchrone, bloquant la gestion des événements jusqu'à la fin. (Tk's _strictly_ single-threaded.) Mon perl est assez rouillé que je ne sais pas comment le réparer. –

+0

Merci Donal, je vais voir s'il y a un moyen de changer cette routine –

+0

salut, avez-vous déjà résolu cela? J'ai un problème similaire avec un appel system() dans une boucle et j'essaye de mettre à jour une étiquette à chaque itération de la boucle, mais à la place elle se bloque jusqu'à ce que la boucle soit terminée. Même l'ajout de DoOneEvent() dans la boucle ne le corrige pas correctement. – insaner

Répondre

0

Je ne sais pas si cela aidera les autres à un problème similaire, mais au cas où il fait:

MainLoop(); 

est ce que « commence » le processus de tk. Une bonne pratique serait de configurer d'abord tous vos widgets, rappels et tout ce que vous voulez afficher à l'écran, puis appelez le MainLoop(). Le traitement doit avoir lieu après le MainLoop() est appelé. Dans ce qui précède, vous aurez probablement besoin d'appeler

$myLabel->update; 

dans la boucle sur tout ce que vous utilisez pour afficher votre sortie. Dans mon cas, j'utilisais un Label pour afficher les messages de progression dans une boucle qui faisait des appels en utilisant system(). En utilisant ->update l'a résolu parfaitement (tandis que DoOneEvent() n'a pas).

Espérons que cela aide quelqu'un.