Problema na atualização da tela de um Installer (Resolvido)

7 respostas
GabrielGarcia

Bom dia a todos.

Eu tenho um probleminha meio chato para resolver.

Estou desenvolvendo um instalador para o sistema da empresa. O projeto é feito em Netbeans.
O mais “complicado” está feito, que seria a cópia dos .ZIP empacotados no JAR para o diretório do sistema, a descompactação dos mesmos e a execução da instalação silenciosa do PostgreSQL, Tomcat e Firefox, além da criação de atalhos e instalação de serviços/Daemon. O Installer funciona em Windows, Linux e Mac.

O programa em si não tem erros, o que me irrita é a tela do instalador.

Para entender o funcionamento dele:

O installer é um JFrame. Dentro dele, possuo um JPanel especializado em desenhar uma Imagem em toda a sua extensão (a imagem que fica ao fundo do Installer). Este Panel está formatado em cardLayout.

Os outros Panels dele são inseridos via código. Montei cada tela do Installer (JPanel) separadamente, sem utilizar o Matisse para inserir diretamente no meu CardLayout Panel. Estes panels são transparentes.

Alguns Panels possuem uma barra de Progresso. Estes panels implementam uma Interface que contém os métodos que possibilitam ao JPanel preencher a barra de progresso e exibir mensagens de instalação.

O processo de atualização da JProgressBar e a exibição das mensagens rodam em uma Thread. A cópia e a descompressão dos arquivos também são executadas em Thread.

O meu problema é: a tela fica completamente congelada, exibindo apenas a mensagem inicial passada a tela. A barra de progresso não fica animada, e a tela apenas se atualiza ao final do processo das operações de IO, no caso, a descompactação dos arquivos .ZIP.

Já tentei updateUI(), repaint(), update(getGraphics()) tanto do JPanel em exibição como da tela principal do Installer que possui a figura do fundo. Usando updateUI() na tela principal, consegui ao menos fazer com que a imagem de fundo apareça, mesmo que desfocada. Sem usar este artifício, a tela ficava branca.

Pode ser algum detalhe específico do Netbeans ou este problema é corriqueiro em interfaces Swing?

Agradeço desde já a ajuda.

PS.: se precisarem de algum trecho de código vou ter que montar algo bem simplificado, porque são muitas classes, e como o installer é multiplataforma, o código é meio extenso.

7 Respostas

GabrielGarcia

OK, resolvido em parte.

Eu realmente estou ficando irritado com o Swing.

Agora a barra e os labels são atualizados em tempo real, porém, estes elementos são "carimbados" em partes aleatórias do JPanel, e o pior de tudo, nem mesmo forçando um update() ou repaint() elas somem.

Alguma dica de como lidar com estes elementos?

Abaixo segue um trecho de código de como eu faço para animar a barra de progressão e alterar o label onde mostro a porcentagem e o caminho completo do arquivo sendo descompactado:

while ((cont = zip.read(buffer, 0, BUFFER_SIZE)) != -1) {
          outStream.write(buffer, 0, cont);
          if (proc != null) {
               copied += cont;
              double auxDPct = (double) copied / size;
              int auxPct = (int) NumberUtil.round(auxDPct * 100);
              if (auxPct != pct) {
                   pct = auxPct;
                   proc.change(zE.getName(), pct);
              }
          }
}

o método change(String, Integer) é o cara que escreve no label de mensagem informando o arquivo sendo copiado (Ze.getName()) e a porcentagem desta cópia (pct). O valor pct também é usado para preencher a barra de progressão desta forma:

javax.swing.SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        lblMessage.setText(s);
                        pgbSt.setValue(p);
                        lblPct.setText(p + "%");
                        frame.update(frame.getGraphics());
                        Thread.yield();
                    }
                });

Alguém sabe como contornar isto?

jctosta

Não tenho certeza se ajuda, mas os teus componentes são double buffered?

GabrielGarcia

DoubleBuffered ou não, ocorre o mesmo erro.

Estou pensando seriamente em ver como um JPanel se comporta ao receber HTML e tentar montar a interface desta forma.

Está ficando improdutivo brigar com uma interface gráfica que parece necessitar de uma polida. Ou eu simplesmente estou fazendo uma caquinha relativamente grande para não conseguir fazer algo que eu considero banal. Pelo menos em Delphi/Visual Studio eu não precisava me preocupar com isso.

jctosta

Não sei se entendi direito, mas você está alterando o conteúdo do JFrame a cada página do Wizard, por que você não utiliza o JLayeredPane e fica apenas trocando as camadas, no caso panels, você mantém toda a ação no JFrame, mas mantém o layout das telas separado em cada um dos Layered Panels.

GabrielGarcia

Eu tenho um JFrame com um JPanel que tem uma imagem de fundo.

Este JPanel usa o layout de cardLayout. Eu insiro novas “páginas” do Wizard neste card, no caso, os JPanels com as suas funções específicas.

Vou ver se com um JLayeredPane eu resolvo este problema.

Ou talvez tentar mexer no JFrame e especializar para desenhar a figura de fundo nele (não sei se isso é possível).

Enfim, agradeço a sugestão. Vou fazer mais uns testes e volto a responder.

Abraço

GabrielGarcia

Boa tarde.

Tentei com JLayeredPane e acontece a mesma coisa.

Estou reescrevendo meu Installer e tentando enxugar o código, além de ter dado uma boa otimizada em alguns processos.

Acho que ainda hoje devo terminar a parte reestruturada de cópia de arquivos que usa JProgressBar. Caso tenha êxito, volto a reportar.

GabrielGarcia

Bom… resolvido. Usei WindowAdapter e JDialog ao invés de um JFrame, usando o mesmo sistema de CardLayout.

Tudo funciona perfeitamente bem agora.

Criado 16 de junho de 2009
Ultima resposta 18 de jun. de 2009
Respostas 7
Participantes 2