Problème de raffraichissement d'élement swing

Problème de raffraichissement d'élement swing - Java - Programmation

Marsh Posté le 09-11-2009 à 22:20:45    

Bonjour, je suis en train de coder un interface swing et je suis confronté à un problème de rafraichissement, voici le code concerné :
 
Un bouton swing avec une méthode associée :

Code :
  1. validateButton.addActionListener(new java.awt.event.ActionListener() {
  2.             public void actionPerformed(java.awt.event.ActionEvent evt) {
  3.  validateButtonPA();
  4.             }
  5.         });


 
Ce que fait la méthode :

Code :
  1. private void validateButtonPA(){
  2. SwingUtilities.invokeLater(new Runnable() {
  3.           public void run() {
  4.             informationArea.setText("Recherche du Naming Service en cours." );
  5.           }
  6.         });
  7. ..................(reste du code de traitement) ..........................
  8. }


 
Le problème est que avec ou sans le invokeLater, le setText ne prend effet que après le code de traitement qui suit.  J'ai beau avoir essayé de rajouter des repaint, revalidate, .... rien n'y fait.
 
Je ne comprends pas ce qui ne va pas, j'ai essayé de suivre le tuto se trouvant à cette adresse http://gfx.developpez.com/tutoriel [...] threading/, mais ça ne semble pas fonctionner comme indiqué.
 
Si quelqu'un voit ce qui ne va pas, merci de ma le signaler  :jap: .
 

Reply

Marsh Posté le 09-11-2009 à 22:20:45   

Reply

Marsh Posté le 09-11-2009 à 23:53:57    

Apparemment tu n'as jamais entendu parler du thread graphique et tu ne sais pas à quoi sert InvokeLater.
 
Donc c'est simple, quand tu cliques sur le bouton, le thread de Swing qui s'occupe de dessiner les fenêtres et réagir aux événements appelle ta méthode validateButtonPA().
Dans cette méthode, tu peux modifier le GUI et lancer des traitements. Donc pas besoin d'InvokeLater ici puisqu'on est déjà dans le thread de Swing.
Ensuite tu as un gros code de traitement. Le traitement en lui-même, tu ne peux pas le faire dans le thread de Swing sinon ton interface graphique freeze puisqu'au lieu de dessiner tes fenêtres, Swing sera occupé à faire tes calculs (c'est le problème que tu observes). Tu dois donc lancer le traitement dans un nouveau thread, et à la fin de celui-ci, tu appelles une fonction au moyen de InvokeLater afin de mettre à jour ton GUI via thread de Swing.
 
Au niveau du code ça donne un truc comme ça:
 
 

Code :
  1. private void validateButtonPA(){
  2.   informationArea.setText("Recherche du Naming Service en cours." );
  3.   new Thread() {
  4.      public void run() {
  5.         // Traitement lourd
  6.         // ...
  7.         SwingUtilities.invokeLater(new Runnable() {
  8.            public void run() {
  9.               informationArea.setText("Recherche du Naming Service terminée." );
  10.            }
  11.         });
  12.      }
  13.   }.start();
  14. }


Message édité par cbeyls le 09-11-2009 à 23:55:50
Reply

Marsh Posté le 10-11-2009 à 10:09:26    

En fait je connais ce qu'est l'EDT, mais une méprise de ma part sur une explication du tutoriel ma fait penser que le actionPerformed s'exécutait dans un thread dédier à l'écoute.
 
J'ai utilisé la classe SwingWorker finalement, et ça fonctionne, mais il y a un truc que je ne comprends pas vis-à-vis de ma situation précédente :
 
Si je fais dans l'EDT :
 

Code :
  1. informationArea.setText("Recherche du Naming Service terminée." );
  2. informationArea.repaint()
  3. //Traitement lourd //


 
Le traitement lourd se situe après la demande de mise à jour de l'interface, pourquoi dès lors l'EDT ne met-il pas à jour l'interface avant de travailler sur le traitement lourd ?
 
Merci pour l'aide  :jap: .

Reply

Marsh Posté le 10-11-2009 à 14:32:35    

A cause de l'ordre des évènements ?

Reply

Marsh Posté le 10-11-2009 à 17:46:30    

Parce que l'EDT fait le travail de redessin de la fenêtre à la fin de l'exécution de ton bloc de traitement des événements. Par souci d'optimisation, il ne lance pas de procédure de redessin à chaque fois qu'on change une propriété du GUI, comme dans ce cas-ci le texte d'un Label. Quand tu changes le texte du Label ou même quand tu appelles repaint(), tu ne fais que demander un redessin ultérieur. Swing fonctionne comme une file d'attente, il attend donc la fin de ton code pour lancer l'opération de dessin suivante, c'est d'ailleurs pour cela que invokeLater() s'appelle invokeLater() et pas invokeNow() :)
C'est pour cela aussi qu'il ne faut jamais bloquer le thread de l'EDT, il doit tourner en permanence pour que l'interface graphique réponde correctement.


Message édité par cbeyls le 10-11-2009 à 17:51:31
Reply

Marsh Posté le 10-11-2009 à 22:14:10    

Merci pour les précisions  :) .

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed