49 votes

SwingUtilities.invokeLater() : pourquoi est-il nécessaire ?

Pourquoi est-il nécessaire de mettre le code de mise à jour de l'interface graphique dans SwingUtilities.invokeLater() ?

Pourquoi cela ne peut-il pas être pris en charge en interne par Swing lui-même ? Pourquoi l'appelant doit-il se soucier de la façon dont Swing gère les mises à jour de l'interface utilisateur ?

1 votes

En fait, cette méthode est précisément destinée au développeur pas de se préoccuper de la synchronisation des fils, car il suffit de faire savoir à Swing qu'il est temps de procéder à une mise à jour, et le gros du travail est effectué en coulisses.

46voto

Richard Fearn Points 11631

Objets oscillants ne sont pas sûrs pour les fils . SwingUtilities.invokeLater() permet d'exécuter une tâche à un moment ultérieur, comme son nom l'indique ; mais surtout, la tâche sera exécutée sur le thread de répartition des événements d'AWT. Lorsque vous utilisez invokeLater la tâche est exécutée de manière asynchrone ; il y a aussi invokeAndWait qui ne reviendra pas tant que l'exécution de la tâche ne sera pas terminée.

Vous trouverez ici des informations sur la décision de ne pas rendre Swing thread-safe : Boîtes à outils multithread : Un rêve raté ? [Archivé]

2 votes

Pourquoi Swing ne peut-elle pas s'en occuper elle-même ? Pourquoi l'appelant doit-il se soucier de la façon dont Swing gère les mises à jour de l'interface utilisateur ?

4 votes

@pure : Parce qu'il est difficile d'y arriver sans pulvériser des verrous partout (AWT l'a fait, et en a souffert). Le fait d'exiger que toutes les mises à jour de l'affichage soient effectuées dans le thread de distribution - ce qui est assez facile au niveau de l'application - fait disparaître la plupart des problèmes.

16voto

Paul Tomblin Points 83687

Parce que les mises à jour de l'interface graphique doivent être effectuées dans le fil de distribution des événements. Si vous travaillez dans un autre thread, la mise à jour doit être effectuée dans le thread de distribution d'événements. invokeLater l'arrache de votre fil et le place dans le fil de l'événement.

Plus d'explications ici : http://www.oracle.com/technetwork/java/painting-140037.html

Pour les mises à jour importantes (comme le repeuplement d'un JTable à partir de la base de données), il est judicieux, dans Swing, de récupérer le modèle sous-jacent, d'effectuer les mises à jour du modèle dans votre thread, puis de lancer une notification en utilisant invokeLater . Cela permet à votre interface de répondre aux événements et de se redessiner. Si la mise à jour est très importante, vous pouvez même envoyer ces notifications avec la commande invokeLater à intervalles réguliers pendant la mise à jour, toutes les secondes ou deux.

9voto

Joey Points 148544

Swing est monofilière. Chaque mise à jour de l'interface utilisateur doit se produisent à partir de ce qu'on appelle l'EDT - le thread de dispersion des événements qui est le thread principal de l'interface graphique que Swing (et je pense AWT) utilise. Si vous ne le faites pas, des choses bizarres peuvent se produire ou se produiront (bien que je préfère Windows Forms qui lève une exception si vous le faites mal).

Ceci étant dit, il n'est pas nécessaire d'envelopper chaque opération de l'interface utilisateur dans un fichier SwingUtilities.invokeLater() - si le code que vous écrivez est déjà exécuté par l'EDT, ce n'est pas nécessaire. Ainsi, le ActionListener pour un clic sur un bouton n'en a pas besoin. Mais un écouteur sur un objet externe, exécuté dans un autre thread, qui met à jour un objet de type JLabel quelque part - là où vous en avez besoin.

5voto

Mark Points 14208

Swing n'a pas été écrit pour être une boîte à outils GUI thread safe, donc toutes les mises à jour GUI doivent se faire à partir d'un seul thread pour éviter les blocages. Dans Swing, il s'agit de l'Event Dispatcher Thread (EDT).

Véase Concurrent en Swing du tutoriel Java pour plus de détails. Il fait également référence à este article de blog sur les raisons pour lesquelles il est difficile d'écrire une boîte à outils GUI multithread.

2voto

Colin Hebert Points 40084

SwingUtilities.invokeLater()

Fait en sorte que doRun.run() soit exécuté de manière asynchrone sur le fil de distribution des événements AWT. Cela se produit après que tous les événements AWT en attente ont été traités. Cette méthode doit être utilisée lorsqu'un thread d'application doit mettre à jour l'interface graphique.
...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X