Mostrar JProgressBar ao abrir sessão do Hibernate [RESOLVIDO]

5 respostas
onyaszimba

Olá, pessoal. Tudo certo?

Não tenho problemas em criar um JProgressBar, mas eu queria criar um que acompanhasse o processo de inicializar o framework Hibernate na aplicação, ou seja, que ficasse enchendo a barra de progresso enquanto o Hibernate abre uma sessão com o método openSession().

Já tentei algumas coisas, como criar um flag, ou criar uma outra Thread para verificar se o Hibernate está com sessão aberta ou não. Primeiramente tentei usar o método isClosed() da sessão, mas não funcionou…

Atualmente, o código da minha Thread que preenche o JProgressBar está assim:

import java.awt.Window;
import javax.swing.JProgressBar;

/**
 * 
 * 
 * @author Onyas D. Claudio
 */
public class UtilProgressBarThread extends Thread {

    /** Determina o valor de início da Thread. */
    public int inicio;
    /** Determina o valor final da Thread. */
    private int fim;
    /** Barra de progresso que vai ser carregada. */
    private JProgressBar progresso;
    /** Tela pai do progressBar que vai ser fechada quando este carregar. */
    private Window telaPai;

    /**
     * Cria uma nova Thread para o progress bar, definindo um valor
     * final de alvo.
     *
     * @param fim determina o valor final.
     */
    public UtilProgressBarThread(int fim, JProgressBar progresso, Window telaPai) {
        inicio = 0;
        this.fim = fim;
        this.progresso = progresso;
        this.telaPai = telaPai;
    } // Fim do construtor

    /** Inicia uma nova <code>Runnable</code>. */
    @Override
    public void run() {

        while (inicio <= fim && !interrupted()) {
            
            HibernateUtil.getSessionFactory().openSession();
            progresso.setValue(inicio);
            try {
                sleep(15);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            } // Fim do controle try/catch

            inicio++;

        } // Fim do while

        telaPai.dispose(); // Quando termina de carregar o hibernate, fecha a tela anterior
        
    } // Fim do método run

} // Fim da classe UtilProgressBarThread

Desse jeito está completamente inútil. Ele carrega a barra depois que o hibernate abriu a sessão e também por um tempo pré-determinado. Gostaria que a barra fosse enchendo de acordo com que o Hibernate fosse inicializando na aplicação.

Estou aberto à idéias. Agradeço desde já.

5 Respostas

R

O método openSession() normalmente é rapidíssimo, creio que na verdade você quer mostrar uma JProgressBar enquanto cria a SessionFactory do Hibernate. O modo como faço em minhas aplicações é criar a SessionFactory na abertura do primeiro formulário, daí em diante as chamadas a openSession() gastam um tempo praticamente desprezível.

A forma como você pode resolver o seu problema é um padrão clássico das aplicações Swing: se você tiver uma tarefa demorada, execute-a sempre numa thread em separado, e faça com que a thread em separado notifique de vez em quando a thread principal do Swing (a famosa EDT - Event Dispatch Thread). A classe SwingWorker foi feita para auxiliar essa tarefa:

http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html

A documentação do método get() mostra um exemplo de como usar uma caixa de diálogo enquanto aguarda uma tarefa terminar, você poderia colocar seu JProgressBar nessa caixa de diálogo:

http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#get()

onyaszimba

Sim, é verdade Roger. Eu fiz uma pequena confusão. O processo é o SessionFactory mesmo.

A minha idéia é ligar o Hibernate quando um usuário fazer o login, e antes de abrir a tela principal da aplicação exibir o JProgressBar para acompanhar o processo. É apenas uma questão estética mesmo.

O problema é a minha falta de experiência com Threads. Por isso vou ler com bastante atenção os links que você me passou. Assim que eu conseguir resolver o problema eu posto aqui.

Brigadão!

ajfilho

Dê uma procurada na classe SwingWorker, pode te ajudar!!

Exemplo de como estou usando a minha:

public class MinhaClasse extends SwingWorker<Void, Integer> {
    private Component tela;
    private JLabel labelProgresso;
    private JProgressBar barraProgresso;

    private MinhaClasse(){
    }

    public MinhaClasse(Component tela, JLabel labelProgresso, JProgressBar barraProgresso){
        this.tela = tela;
        this.labelProgresso = labelProgresso;
        this.barraProgresso = barraProgresso;
    }

    @Override
    protected Void doInBackground() throws Exception {
        labelProgresso.setText("Carregando Dados...");
        construirEntityManagerFactory();
        Thread.sleep(1500);
        labelProgresso.setText("Dados carregados com sucesso.");
        Thread.sleep(1500);
        labelProgresso.setText("Abrindo Aplicação...");
        Thread.sleep(2000);
        tela.setVisible(false);
        new TelaPrincipal().setVisible(true);
        return null;
    }
}

Em seguida, na minha classe em que se encontra o JProgressBar eu faço isso no construtor:

MinhaClasse minhaClasse = new MinhaClasse(this, lblProgresso, brProgressoAbertura);
minhaClasse.execute();

Eu coloquei esse Thread.sleep() pq depois que ele carrega a sessionFactory(), abria a nova tela instantaneamente. Eu quiz que atualizasse os labels para que o usuário
percebesse melhor.

Obs: Defina a propriedade do seu JProgressBar.setIndeterminate() como true

Abraços!

onyaszimba

Funcionou! Segui esse seu modelo Augusto e consegui fazer o JProgressBar aparecer enquando o Hibernate carregava o seu SessionFactory. Valeu pela sua ajuda e pela do Roger.

Eu queria que a barra preenchesse, e não usar o indeterminate. Mas isso eu quero descobrir sozinho como fazer.

Só que, tudo bem, eu consegui fazer o que queria. Mas surgiram algumas dúvidas e queria entender um pouco mais sobre o funcionamento do SwingWorker. Falar a verdade, só agora que eu soube da sua existência.

A minha dúvida é ali no extends, ele recebe dois parâmetros: Void e Integer. Queria saber como esses dois parâmetros agem na classe e qual seriam a função deles?

onyaszimba

Para mostrar como ficou o código:

import gui.GUIPrincipal2;
import java.awt.Window;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

/**
 *
 * 
 * @author Onyas D. Claudio
 */
public class UtilProgressoHibernate extends SwingWorker<Void, Integer> {

    private Window telaPai;
    private JProgressBar progresso;

    public UtilProgressoHibernate(Window telaPai, JProgressBar progresso) {
        this.telaPai = telaPai;
        this.progresso = progresso;
    } // Fim do construtor


    @Override
    protected Void doInBackground() throws Exception {

        HibernateUtil.getSessionFactory();
        Thread.sleep(1000);

        // Se quiser, posso colocar outros processos demorados aqui...

        this.telaPai.dispose(); // Ao final, fecho a janela do JProgressBar...

        new GUIPrincipal2().setVisible(true); //...e mostro a tela principal da aplicação.

        return null;
    } // Fim do método doBackground

    
} // Fim da classe UtilProgressoHibernate

Depois é só executar a JProgressBar:

public JProgressBar jpbProgresso;

    /** Cria um novo formulário GUIPanelProgressBar. */
    public GUIPanelProgressBar(Window telaPai) {
        initComponents();

        jpbProgresso.setIndeterminate(true);
        UtilProgressoHibernate progHibernate = new UtilProgressoHibernate(telaPai, jpbProgresso);
        progHibernate.execute();

        this.setVisible(true);
    } // Fim do construtor

Obrigado à todos que tiveram paciência de resolver minha dúvida.

Criado 25 de setembro de 2009
Ultima resposta 28 de set. de 2009
Respostas 5
Participantes 3