Barra de progresso em geração de relatório

6 respostas
J

Olá pessoal,

Estou tendo um problema aqui, implementei uma classe grafica para geração de relatórios e quando mando gerar os relatórios tem uma barra de progresso que fica indicando que o relatório está sendo gerado. até aí tudo bem, mando gerar o relatório em uma Thread com um Observer e tal, mando gerar e tudo funfa de boa, mas isso somente com os Look and Feels padrão do java, o Metal, Nimbus e Windows. Mas estou utilizando o Substance para LAF, aí mando gerar e ele gera uma exceção dizendo que o JasperViewer precisa ser criado em uma thread… blz… vou lá a adiciono um EventQueue.invokeLater(new Runnable() {} e ele gera o relatório normal, mas agora fica sem a minha barra de progresso e volta a travar a tela.

Se eu retiro o EventQueue.invokeLater(new Runnable() {} da parte de Thread e troco o LAF ele gera o relatório de boa com a barra de progresso, mas se coloco o Substance ele somente roda em Thread-safe e trava novamente a minha tela na hora de instanciar a classe JasperViewer e não mostra mais a minha barra de progresso.

Alguem tem idéia de como tratar isso com o substance?
Não quero colocar um LAF padrão…

6 Respostas

P

Aperta alt+f4 resolbvera seu problema

J

Meu camarada, acho que vc não me entendeu. Eu não quero q o sistema trave ao invocar o EventQueue.invokeLater(new Runnable() {} para instanciar o JasperViewer. Quero que a barra de progresso seja mostrada normalmente até abrir o viewer do JasperReports.

L

Tava com esse mesmo problema ate descobrir que eu fazia o processo de atualização errado. Detalhe com o substance fica muito mais lento do que com o metal.
Só que funciona para qualquer look And Feel

Segue o codigo

Setar o Maximum value da progressBar

private void setMaximumProgress(final int valor)
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				pbProgresso.setIndeterminate(false);
				pbProgresso.setValue(0);
				pbProgresso.setMaximum(lista.size());
			}
		});
	}

Adicionar Progresso na Barra

private void addProgress(final int posicao)
	{
		try
		{
			SwingUtilities.invokeAndWait(new Runnable()
			{
				@Override
				public void run()
				{
					pbProgresso.setValue(posicao);
				}
			});
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

Atualizar Label se existir

private void setTextProgress(final String texto)
	{
		try
		{
			SwingUtilities.invokeAndWait(new Runnable()
			{
				@Override
				public void run()
				{
					lblStatus.setText(texto);
				}
			});
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

Outras informações a barra de progresso nao e bom vc pegar o value dela + 1 e melhor passar o valor total dela de uma vez, e sempre que for um processo que voce deseja atualizar a tela vc deve usar a api SwingUtilities.invokeLater e SwingUtilities.invokeAndWait

J

Já testei com o SwingUtilies também, mas o processo de pegar o JasperPrint e mostrar com o JasperViewer trava a minha tela e não mostra a barra. O estranho é que com os outros LAFs padrão do JDK rodam normalmente.

Método que cria a Thread para executar o relatório.
private void executaRelatorio(){
        ValidaDatasPorTipoDeRelatorio valida = new ValidaDatasPorTipoDeRelatorio();
        if (valida.validarRelatorioTotalDePassageiroPorLinha(txtDataInicio.getDate(), txtDataFim.getDate()) == true) {
         
            if (processarRelatorio == null) {

                String DATA_INICIO = new SimpleDateFormat("yyyy-MM-dd").format(txtDataInicio.getDate());
                String DATA_FIM = new SimpleDateFormat("yyyy-MM-dd").format(txtDataFim.getDate());

                processarRelatorio = new Thread(new RelatorioProcesso(this, DATA_INICIO, DATA_FIM));
                processarRelatorio.start();
            } else {
                JOptionPane.showMessageDialog(this, "Outro relatório já está sendo gerado.");
            }
        }
    }
Método que atualiza a barra de progresso que recebe Observable como parâmetro.
public void update(Observable o, Object arg) {
        if (arg.toString().equals("1")){
            progressBarRelatorio.setVisible(true);
            progressBarRelatorio.setIndeterminate(true);
            progressBarRelatorio.setString("Gerando relatório...");
            progressBarRelatorio.setStringPainted(true);
        } else {
            progressBarRelatorio.setVisible(false);
            progressBarRelatorio.setIndeterminate(false);
            progressBarRelatorio.setString(null);
            progressBarRelatorio.setStringPainted(false);
            processarRelatorio = null;
        }
    }
A classe que que faz o processo de chamar o relatório.
private class RelatorioProcesso extends Observable implements Runnable {

        private String DATA_INICIO = null;
        private String DATA_FIM = null;

        /**
         * Construtor
         * @param observador é a classe a ser observada.
         */
        public RelatorioProcesso(Observer observador, String DATA_INICIO, String DATA_FIM) {
            addObserver(observador);
            this.DATA_INICIO = DATA_INICIO;
            this.DATA_FIM = DATA_FIM;
        }

        public void run() {
            setChanged();
            notifyObservers("1");

            emite();

            setChanged();
            notifyObservers("");
        }

        private void emite() {
            EmiteRelatorios emitirRelatorio = new EmiteRelatorios();
            emitirRelatorio.RelatorioTotalDePassageiroPorLinha(DATA_INICIO, DATA_FIM);
        }
    }
E a minha classe com o relatório.
public class EmiteRelatorios {

    /**
     * Gera o relatório de Total de Passageiro por Linha.
     * @param DATA_INICIO É a data inicial do período do relatório.
     * @param DATA_FIM É a data final do período do relatório.
     */
    public void RelatorioTotalDePassageiroPorLinha(final String DATA_INICIO, final String DATA_FIM){
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {

                    Session sessao = null;
                    InputStream relatorio = null, IMAGEM_INICIO = null;
                    try {
                        relatorio = getClass().getResourceAsStream("/br/com/tecnicgvbus/relatorios/jaspers/PassageiroTotalLinha.jasper");
                        IMAGEM_INICIO = getClass().getResourceAsStream("/br/com/tecnicgvbus/imagens/Relatorio.jpg");
                        sessao = HibernateUtil.getSessionFactory().openSession();

                        HashMap parametros = new HashMap();
                        parametros.put("DATA_INICIO", DATA_INICIO);
                        parametros.put("DATA_FIM", DATA_FIM);
                        parametros.put("IMAGEM_INICIO", IMAGEM_INICIO);

                        JasperPrint jPrint = JasperFillManager.fillReport(relatorio, parametros, sessao.connection());
                        JasperViewer jView = new JasperViewer(jPrint, false);

                        jView.setSize(1024, 768);
                        jView.setTitle("Relatório de Passageiros por Linha");
                        jView.setExtendedState(JFrame.MAXIMIZED_BOTH);
                        jView.setVisible(true);

                        sessao.close();
                    } catch (Exception e) {
                        System.out.println(e);
                        JOptionPane.showMessageDialog(InicioView.getInicioView(), "Erro ao gerar relatório.\n\nErro:\n" + e + "\n\nContate o administrador do sistema");
                    } finally {
                        try {
                            if (sessao.isOpen()) {
                                sessao.close();
                            }
                            relatorio.close();
                        } catch (Exception e) {/*discard it*/

                        }
                    }
                }
            });
    }
}

O problema está na linha 25 da classe EmiteRelatorios quando ele chama o JasperViewer, note que já estou utilizando o SwingUtilies, mas mesmo assim ele trava a minha tela. Porém se eu colocar algum dos LAFs padrão do JDK ele não trava a tela...

Será que realmente isso é assim somente por causa do substance?

J

O erro que tenho quando usutilizo o substance sem usar o SwingUtilies para criar o JasperViewer é:

org.pushingpixels.substance.api.UiThreadingViolationException: Component creation must be done on Event Dispatch Thread

é aí que crio a thread com o SwingUtilies para chamar o JasperViewer, mas a barra não é mostrada e a aplicação trava até que o relatório seja gerado.

J

Troquei o Look and Feel e funfou de boa. A partir daqui não utilizarei mais o substance, percebí um aumento notável na velocidade do sistema ao retirar o substance.

Estou utilizando o TinyLaF : http://www.muntjak.de/hans/java/tinylaf/index.html e o LipstickLF : http://sourceforge.net/projects/lipstiklf/

Valeu a todos.

Criado 1 de outubro de 2010
Ultima resposta 4 de out. de 2010
Respostas 6
Participantes 3