SwingUtilities.invokeLater

Minha pergunta está relacionada ao SwingUtilities.invokeLater . Quando devo usá-lo? Preciso usar cada vez que preciso atualizar os componentes da GUI? O que exatamente faz? Existe uma alternativa para isso, pois não soa intuitivo e adiciona código aparentemente desnecessário?

Preciso usar cada vez que preciso atualizar os componentes da GUI?

Não, não se você já estiver no segmento de expedição de events (EDT), que é sempre o caso ao responder a events iniciados pelo usuário, como cliques e seleções. (Os methods actionPerformed etc, são sempre chamados pelo EDT.)

Se você não estiver no EDT e quiser fazer atualizações de GUI (se quiser atualizar a GUI de algum thread de timer ou de algum thread de rede, etc.), será necessário programar a atualização a ser executada pelo EDT. . É para isso que serve esse método.

Swing é basicamente thread inseguro. Ou seja, toda a interação com essa API precisa ser executada em um único thread (o EDT). Se você precisar fazer atualizações de GUI de outro thread (thread timer, thread de rede, …) você precisa usar methods como o que você mencionou (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, …).

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

Uso básico para invokeLater()

  1. Os principais methods devem sempre ser invokeLater() em invokeLater()

  2. Ação / evento atrasado (mas de forma assíncrona) até o final de EventQueue ,

  3. Se o EDT não existir, você precisará criar um novo EDT usando invokeLater() . Você pode testá-lo com if (SwingUtilities.isEventDispatchThread()) {...

  4. Existe invokeAndWait() , mas até hoje eu (do meu ponto de vista) não consigo encontrar uma razão para usar invokeAndWait() vez de invokeLater() , exceto mudanças difíceis em GUI (JTree & JTable), mas apenas com Substance L & F (excelente para testar a consistência de events no EDT)

  5. Material básico: concurrency no Swing

  6. Todas as saídas de tarefas em segundo plano devem ser invokeLater() em invokeLater()

Cada aplicativo Swing tem pelo menos 2 threads:

  1. O thread principal que executa o aplicativo
  2. O EDT (Event Dispatching Thread) é um thread que atualiza a interface do usuário (para que a interface do usuário não congele).

Se você deseja atualizar a interface do usuário, execute o código no EDT. Métodos como SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait permitem que você execute código pelo EDT.

Minha pergunta desta vez está relacionada ao SwingUtilities.invokeLater : Quando devo usá-lo?

O que é importante entender é que o Java tem um thread separado (EDT) que manipula events relacionados ao Swing.

Você deve usar invokeLater() para exibir o JFrame principal de um aplicativo da área de trabalho (por exemplo), em vez de tentar fazê-lo no encadeamento atual. Ele também criará o contexto para o fechamento da aplicação mais tarde.

É sobre isso para a maioria das aplicações.

Preciso usar cada vez que preciso atualizar os componentes da GUI? O que exatamente faz?

Não. Se você modificar um componente da GUI, ele acionará um evento que é registrado para envio posterior pelo Swing. Se houver um ouvinte para este evento, o segmento EDT irá chamá-lo em algum lugar abaixo da estrada. Você não precisa usar invokeLater() , basta definir seus ouvintes nos componentes corretamente.

Tenha em mente que este segmento é o mesmo quadro de desenho de linha, etc … na sua canvas. Portanto, os ouvintes não devem executar tarefas complexas / longas / que exijam muita utilização da CPU; caso contrário, sua canvas congelará.

Existe uma alternativa para isso, pois não soa intuitivo e adiciona código aparentemente desnecessário?

Você não precisa escrever mais código do que exibir seu aplicativo com invokeLater() + listeners nos quais você está interessado no componente. O resto é tratado pelo Swing.

A maioria dos events iniciados pelo usuário (cliques, teclado) já estará no EDT, portanto, você não precisará usar o SwingUtilities para isso. Isso abrange muitos casos, com exceção do thread principal () e dos threads de trabalho que atualizam o EDT.