Pergunta

Estou usando uma API em uma biblioteca Java, que é chamada do thread de expedição de eventos e exige que eu retorne um componente UI totalmente inicializado. Se parece com isso:

public JDialog createDialog();

Mas só posso preencher a caixa de diálogo após o carregamento de um banco de dados, que pode levar 10 segundos às vezes. Normalmente, eu faria isso em um encadeamento de segundo plano, mas como esse método é chamado do EDT e, como tenho que devolver a caixa de diálogo, isso não funcionará. É uma biblioteca de terceiros, então não posso mudar o método, mas há algo que eu possa fazer para evitar bloquear o EDT?

Foi útil?

Solução

"Inicializado" não é necessariamente a mesma coisa que "povoado". "Inicializado" geralmente significa que o objeto foi totalmente construído, mas pode não ter nenhum dado. "Populado", é claro, significa que os dados estão presentes e quaisquer tarefas de busca de dados estão concluídas. Portanto, é possível dar à sua biblioteca de terceiros um JDialog totalmente inicializado, sem nenhum dados.

A maneira como eu sempre gosto de resolver esse problema é criar um JDialog personalizado que exibe uma mensagem ocupada ou uma barra de progresso ou similares e solicitar os dados em outro thread. Quando os dados são retornados, substituo a mensagem ocupada pelos dados (no EDT!). Quanto à forma como você deve executar sua solicitação em um tópico em segundo plano, eu recomendo o uso de trabalhadores de swing. Eu gosto de usar um particular SwingWorker dentro do meu jdialog personalizado, que lida com a solicitação no doInBackground() método e lida com as tarefas relacionadas à exibição no done() método. Fazer dessa maneira garantirá que as tarefas relacionadas à exibição ocorram apenas no EDT, e as tarefas relacionadas ao banco de dados ocorrem apenas no EDT. Se você quiser uma introdução razoavelmente boa para usar os trabalhadores de swings, confira Tutorial do Sun sobre tópicos de trabalhadores. Um exemplo simples seria:

public class DBDIalog extends JDialog{
     private JLabel busyLabel = new JLabel("Fetching data from DataBase");

     public DBDialog(){
         //do your initialization stuff here
     }

     private class DBFetcher extends SwingWorker<Void,DBInfo>{

        @Override
        protected DBInfo doInBackground() throws Exception{
            return fetchDataFromDB(); //or whatever database call to make
        }

        @Override
        protected void done(){
           try{
               DBInfo info = get();
           //replace your busy label with your DBInfo
           }catch(InterruptedException e){
              //do appropriate thread interrupted stuff
           }catch(ExecutionException e){
              //do appropriate general error handling stuff 
           }

        }
     }
}

Algumas coisas a lembrar, no entanto: o done() O método não é abstrato, então você não é obrigado a substituí -lo. Você deveria, no entanto. Se seu doInBackground() A implementação lança uma exceção, essa exceção será engolida, a menos que done() foi substituído. Além disso, não faça alterações na sua GUI de dentro do doInBackground(), a menos que você use SwingUtilities.invokeLater(Runnable), Como doInBackground() é executado a partir de um encadeamento diferente do EDT e fazer alterações na GUI de um thread em segundo plano está pedindo bugs estranhos e inexplicáveis.

Quando isso deve ser usado? Ao contrário de outras tarefas de programação, o ponto em que algo leva muito tempo para responder é muito mais curto em GUIs-o número que eu geralmente vi escrito é de cerca de 250ms. Se sua tarefa levar mais tempo do que isso, ela deve estar em um tópico de segundo plano. No seu caso, 10 segundos devem definitivamente Esteja em um tópico de segundo plano, mas você já sabia disso :)

EDITAR:

Vendo seu comentário, vejo que a maior parte do meu post é bastante discutível. No entanto, você ainda pode usar um trabalhador de swing:

Peça ao seu swingworker executar a retirada de dados e no done() Método, faça com que construa o JDialog a partir dos dados e entrega essa caixa de diálogo para sua biblioteca de terceiros.

Outras dicas

Construa a caixa de diálogo sem dados e inicie uma tarefa para preenchê -lo.

Do ponto de vista da experiência do usuário, qualquer coisa que leve 10 segundos desde a iniciação até a conclusão seja um problema. É melhor se você deve algo Imediatamente, mesmo que não esteja na forma final. Se necessário, você pode colocar uma caixa de diálogo modal que simplesmente diz "carregando".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top