web-dev-qa-db-fra.com

SwingUtilities.invokeLater

Ma question concerne SwingUtilities.invokeLater. Quand devrais-je l'utiliser? Dois-je utiliser chaque fois que je dois mettre à jour les composants de l'interface graphique? Que fait-il exactement? Existe-t-il une alternative car il ne semble pas intuitif et ajoute du code apparemment inutile?

52
FadelMS

Dois-je utiliser chaque fois que je dois mettre à jour les composants de l'interface graphique?

Non, pas si vous êtes déjà sur le thread de distribution d'événements (EDT), ce qui est toujours le cas lorsque vous répondez à des événements déclenchés par l'utilisateur tels que des clics et des sélections. (Les méthodes actionPerformed etc, sont toujours appelées par l'EDT.)

Si vous n'êtes pas sur l'EDT cependant et que vous souhaitez faire des mises à jour de l'interface graphique (si vous souhaitez mettre à jour l'interface graphique à partir d'un thread de minuterie ou d'un réseau thread etc.), vous devrez planifier la mise à jour à effectuer par l'EDT. C'est à ça que sert cette méthode.

Le swing est fondamentalement dangereux pour les threads. C'est-à-dire que toutes les interactions avec cette API doivent être effectuées sur un seul thread (l'EDT). Si vous devez effectuer des mises à jour de l'interface graphique à partir d'un autre thread (thread du minuteur, thread de mise en réseau, ...), vous devez utiliser des méthodes telles que celle que vous avez mentionnée (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...).

52
aioobe
Swing is single threaded and all changes to the GUI must be done on EDT 

Utilisation de base pour invokeLater()

  1. Les méthodes principales doivent toujours être enveloppées dans invokeLater()

  2. Action/événement retardé (mais de manière asynchrone) à la fin de EventQueue,

  3. Si l'EDT n'existe pas, vous devez créer un nouvel EDT en utilisant invokeLater(). Vous pouvez le tester avec if (SwingUtilities.isEventDispatchThread()) {...

  4. Il existe invokeAndWait(), mais jusqu'à aujourd'hui, je (juste ma vue) ne peux pas trouver de raison d'utiliser invokeAndWait() au lieu de invokeLater(), à l'exception des changements importants dans l'interface graphique ( JTree & JTable), mais juste avec Substance L&F (excellent pour tester la cohérence des événements sur l'EDT)

  5. Trucs de base: concurrence dans Swing

  6. Toutes les sorties des tâches en arrière-plan doivent être enveloppées dans invokeLater()

14
mKorbel

Chaque application Swing a au moins 2 threads:

  1. Le thread principal qui exécute l'application
  2. L'EDT (Event Dispatching Thread) est un thread qui met à jour l'interface utilisateur (afin que l'interface utilisateur ne se fige pas).

Si vous souhaitez mettre à jour l'interface utilisateur, vous devez exécuter le code dans l'EDT. Des méthodes telles que SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait vous permettent d'exécuter du code par l'EDT.

7
Ammar

Ma question cette fois est liée à SwingUtilities.invokeLater: Quand dois-je l'utiliser?

Ce qui est essentiel à comprendre, c'est que Java a un thread séparé (EDT) gérant les événements liés à Swing.

Vous devez utiliser invokeLater() pour afficher le JFrame principal d'une application de bureau (par exemple), au lieu d'essayer de le faire dans le thread actuel. Il créera également le contexte de la fermeture progressive de l'application ultérieurement.

C'est à peu près tout pour la plupart des applications.

Dois-je utiliser chaque fois que je dois mettre à jour les composants de l'interface graphique? Que fait-il exactement?

Non. Si vous modifiez un composant GUI, il déclenchera un événement qui sera enregistré pour une distribution ultérieure par Swing. S'il y a un écouteur pour cet événement, le thread EDT l'appellera quelque part sur la route. Vous n'avez pas besoin d'utiliser invokeLater(), placez juste vos écouteurs sur les composants correctement.

Gardez à l'esprit que ce fil est le même cadre de dessin de fil, etc. sur votre écran. Par conséquent, les auditeurs ne doivent pas effectuer de tâches complexes/longues/gourmandes en CPU, sinon votre écran se fige.

Existe-t-il une alternative car elle ne semble pas intuitive et ajoute du code apparemment inutile?

Vous n'avez pas besoin d'écrire plus de code que d'afficher votre application avec invokeLater() + écouteurs qui vous intéressent sur le composant. Le reste est géré par Swing.

7
Jérôme Verstrynge

La plupart des événements déclenchés par l'utilisateur (clics, clavier) seront déjà sur l'EDT, vous n'aurez donc pas à utiliser SwingUtilities pour cela. Cela couvre de nombreux cas, à l'exception de votre thread principal () et des threads de travail qui mettent à jour l'EDT.

3
Garrett Hall