Progress Bar / Pogress Monitor

Boa tarde, pessoal…

Estou com o seguinte problema:
Minha aplicação, por fazer muito, mas muitos acessos a um banco de dados, demora para caregar.
Então, a idéia foi colocar um progress bar. Só que o java, na hora de executar todos os métodos, simplesmente instancia um componente, e antes mesmo de terminar de construí-lo, o java já instancia o proximo.
Isto acarreta que a barra de progresso chega ao fim muito, mas muito antes de toda a tela do aplicativo, que é formada por difeentes componentes, fique pronta.

Gostaria de saber se existe alguma meneira fazer com que a progress bar chegue ao fim somente quando toda a aplicação estiver carregada.

Meu problema não é em relação ao tempo. Só queria que a progress bar mostrasse exatamente o progresso de carga do meu aplicativo.

Obrigado desde já.

Abraços.

Pergunta 1: vc está instanciando objetos de onde? O Java tá usando várias threads pra instanciar os objetos? Eles por acaso vêm do banco??

Pergunta 2: Vc conta o objeto como “pronto” no construtor? O melhor é ter um método só pra isso que atualiza sua contagem, e chamá-lo no final da carga. Sempre no fim.

De modo geral, vc tem que atualizar o Monitor quando o objeto terminou de construir… eu sei que é meio óbvio, mas olhando bem pro seu código vc vai achar um lugar melhor pra colocá-lo.

[]s do duke!!

Vou tentar ser mais claro.
Tenho uma classe principal que é um JFrame. Nesta JFrame, são instanciado e inseridos, entre outras coisas, um objeto Canvas, JToolBar, JTable, 3 JPanels.

Para isto, criei um método para instanciar e inserir cada um no JFrame. Exemplo: addCanvas(), addToolbar(), etc.

Daí criei um método que chama todos estes acima em sequencia. Entre a chama de cada um, eu vou aumentando a barra de progresso.

O Problema: A barra de progresso sempre chega ao seu final muito antes de todas os objetos terminarem de ser instanciados.

Dados importantes adicionais: Todas as classes citadas acima, sem excessão, fazem acesso a banco de dados. O canvas é o mais pesado de todos. Leva algo em torno de 50 segundos para teminar de carregar, pois precisa ir no banco buscar informações sobre o que ele deve pintar.

O que eu notei foi que ele chama, por exemplo, o método addCanvas(), e, sem esperar que o objeto seja totalmente intanciado, ele já chama o proximo método.

Obs: Não uso nenhum Thread.

Isto está me deixando sem cabelos.

Se alguem tiver alguma idéia, me avise.

Muito obrigado…

Ola,

Sem usar Thread você não vai conseguir fazer o que você quer.

Uma saída rápida, indolor mas não muito profissa …

Ao chamar suas funcoes faca assim:

descricaoDaEtapa.setText("Carregando canvas");
try {
            SwingUtilities.invokeLater(new Runnable() { 
                   public void run() 
                   { 
                      addCanvas();
                   } 
                });
} catch(Exception e) {
}
descricaoDaEtapa.setText("Canvas carregado");
barraDeStatus.setValue(barraDeStatus.getValue()+1);

Fiz o que vc me pediu, mas o java executou as duas instruções abixo do Try antes de terminar de riar o Canvas.

Não sei mais o que fazer. Entendi o que vc me disse. A idéia parece funcional. Só que ele sai do invokeLater antes de terminar todas as instruções.

Sei lá, isto esta muito estranho…

Mas valeu. Valeu mesmo.

Se vc tiver mais alguma idéia, ou se vc acha que eu to errando em algum lugar, e só me dizer.

Se vc quiser, eu posso te mandar o código do método em questão. Só não posso te mandar o código inteiro por causa de normas aqui da empresa.

Obrigado

Vixe, mil desculpas …

errei de instrução … ao inves de SwingUtilities.invokeLater utilize SwingUtilities.invokeAndWait … o resto continua igual :slight_smile:

[]s

Não, não, não use a AWT Dispatcher pra fazer sua carga no banco! Vc vai ficar totalmente sem eventos…

Deixa eu perguntar: vc faz todas essas chamadas (por exemplo, a addCanvas() e ao método que aumenta o progresso) dentro do construtor??

O lance é que se vc compila com otimização, o Java pode trocar instruções de posição quando tem I/O. Já que todas as suas classes fazem I/O, ele acaba executando as instruções “off-screen” pra gerar os eventos o quanto antes.

Veja se seu comando pra compilar manda ele otimizar o código, e se tirar a otimização “parece” resolver. É claro que vc vai querer otimizar o seu código, então…

O tutorial da Sun “How to Use Progress Bars” também usa uma SwingWorker, um Objeto que executa uma tarefa e, quando terminado, faz alguma coisa no Swing.

O tutorial está aqui:
http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html

E aqui fala sobre o SwingWorker:
http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#SwingWorker

A melhor abordagem é provavelmente criar um método updateProgress() que marca o seu progresso e chamá-lo ao longo das tarefas, e não entre métodos. Uma coisa que você pode fazer é declarar voláteis suas variáveis de instância:

  public volatile Canvas canvas;

Isso impede o Java de trocar de ordem as leituras e as escritas dessa variável, portanto necessariamente esse código vai executar na ordem:

  ... // começo do método
  addCanvas();
  while (canvas == null); // busy wait
  updateProgress();

Isso é um monte de chutes pra vc tentar todos… :wink:

[]s

Quando vc me mandou a outra instrução, e vi que no meu caso ela não tinha funcionado, também tentei invokeAndWait. Tinha um exemplo lá no java.
Ele melhora um pouco o carreagmento, pois ele espera um pouco antes de chamar a proxima instrução. Só que ño meu caso ele não funcionou. Chega-se ao fim das instruções antes do termino da criação das classes.

Vou tentar olhar este método q vc me falou lá na API, talvez eu esteja errando em algum lugar.

Mesmo asssim, valeu…

Vou tentar usar este método q vc me mandou novamente.

Obrgado