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

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…

Aperta alt+f4 resolbvera seu problema

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.

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á 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.

[code] 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.");
        }
    }
}[/code]

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.

[code] 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);
    }
}[/code]

E a minha classe com o relatório.

[code]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*/

                    }
                }
            }
        });
}

}[/code]

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?

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.

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.