2010-11-22 5 views
4

J'ai beaucoup essayé, mais je n'arrive pas à le faire fonctionner.Comment mettre à jour l'étiquette de JFrame dans un fil? - Java

On m'a dit d'utiliser EDT avec l'exemple suivant.

SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      // Modify the GUI here 
     } 
}); 

J'ai beaucoup lu sur ce sujet et je ne comprends toujours pas. Je comprends ce qu'est un fil, mais le .invokeLater n'a toujours aucun sens pour moi. Honnêtement si vous pouvez expliquer en détail ce serait une grande aide!

But du programme: Pour obtenir la clé générée de manière aléatoire qui est constamment créée chaque seconde pour se mettre à jour par la suite dans l'interface graphique.

+1

En plus de la réponse de @John V. ci-dessous, vous pouvez lire cet article: [Threads and Swing] (http://java.sun.com/products/jfc/tsc/articles/threads/threads1 .html) – casablanca

Répondre

3

Il existe donc un EDT (thread d'envoi d'événement). Toutes les actions qui apparaissent sur votre écran sont exécutées par l'EDT. Il n'y a qu'une seule EDT par application swing.

Vous êtes dans un thread arbitraire et vous souhaitez mettre à jour le QUI via ce thread? Comme je l'ai dit il n'y a qu'un EDT pour chaque application swing, donc vous devez dire à EDT d'afficher l'étiquette (ou le contexte que vous voulez). L'idée ici est de pousser ce Runnable dans une file d'attente d'où provient l'EDT. Finalement, votre runnable sera traité par l'EDT quand toutes les autres actions avant lui sont copmpleted.

0

Si vous cherchez à faire est de mettre à jour l'interface utilisateur sur un calendrier connu, essayez quelque chose comme ce qui suit. Cela suppose qu'un JFrame est le composant que vous souhaitez mettre à jour toutes les secondes.

private static final int WAIT_LENGTH = 1000; // 1 second 
private JFrame frame = new JFrame(); 

// Thread will update the UI (via updateUI() call) about every 1 second 
class UIUpdater extends Thread { 
    @Override 
    void run() { 
    while (true) { 
     try { 
     // Update variables here 
     } 
     catch (Exception e) { 
     System.out.println("Error: " + e); 
     } 
     finally { 
     frame.repaint(); 
     Thread.sleep(WAIT_LENGTH); 
     } 
    } 
    } 
} 

Pour démarrer cette discussion:

UIUpdater t = new UIUpdater(); 
t.start(); 
+0

.updateUI(); continue à venir avec une erreur et quand jamais j'essaye de changer l'étiquette avec .setText(); où vous avez posté // Mettre à jour les variables ici, je finis toujours par ne pas m'aider. Donc je pensais qu'au lieu de JFrame j'aurais besoin du mainFrame (qui étend le JFrame que j'ai utilisé auparavant) et donc ça n'a pas fonctionné ... donc en gros je ne vois pas où c'est supposé me laisser le mettre à jour. Je vais lire le livre a suggéré "Filthy Rich Clients" à coup sûr ... – Zeveso

+0

Il s'avère que 'component.repaint()' est plus dans le sens de ce que vous cherchez. Pardon. J'ai mis à jour ma réponse. –

1

Je vous recommande de faire le livre Filthy Rich Clients. Il y a un chapitre où ils expliquent le modèle de filetage de Swing dans les moindres détails.

Fondamentalement, dans Swing, tout code qui modifie l'interface graphique doit être exécuté dans le thread Dispatcher d'événements. La classe SwingUtilities que vous utilisez ici vous permet de publier facilement des événements dans la file d'attente d'événements qui est ensuite envoyée par l'EDT. C'est ce que fait la méthode invokeLater, il faut un new Runnable() comme argument qui est finalement exécuté sur l'EDT.

Extrait du livre:

La mise en œuvre invokeLater() prend soin de créer et de faire la queue un événement spécial qui contient le Runnable. Cet événement est traité sur l'EDT dans l'ordre , il a été reçu, comme tout autre événement . Lorsque le moment est venu, il est envoyé en exécutant la méthode run() runner de .

+0

Je vais recevoir ce livre ce soir, merci pour cette suggestion – Zeveso

0

Ceci est un élément assez commun de toute la programmation GUI. Vous avez un thread qui gère le dessin de l'interface graphique, obtenir des entrées et exécuter des rappels. Si un autre thread essaie de modifier les objets liés à l'interface graphique, il sera en conflit avec le thread graphique. Dis, par exemple, il était à mi-chemin de dessiner quelque chose et vous changez la couleur d'un fil différent.

Tout invokeLater met en file d'attente quelque chose pour le thread graphique à exécuter. Par "plus tard", il fonctionne vraiment presque instantanément mais le thread actuel n'a pas à l'attendre. Le thread GUI peut faire un draw ou attendre un callback à retourner ce qui retarderait l'exécution du code que vous lui avez donné.

0

doit être un membre afin que nous puissions changer et toujours l'utiliser d'une classe interne

protected long secret=0; 

... cela doit être dans votre code quelque part, il va se lancer ...

JFrame f = new JFrame("foo"); 
new Thread(){ 
     public void run() { 
      for(;;){ 
       try { 
        sleep(1000); 
       } catch Interrupted (Exception ix){ 
        return; 
       } 
       // TODO update your secret key here 
       // please don't use random() 

       SwingUtilities.invokeLater(new Runnable() { 
        public void run() { 
         f.setTitle("secret "+x); 
        } 
       }); 
      } 
     } 
    }).start(); 

....

Seulement jamais mettre à jour oscillation de l'EDT afin qu'il peint correctement. Lorsque vous êtes dans l'EDT (code courant dans un gestionnaire d'événements), vous pouvez appeler paintImmediately() si vous le voulez vraiment.

Questions connexes