[Resolvido] ProgressBar enquanto atualiza BD

3 respostas
Z

Pessoal,
Estou com o seguinte problema:
Tenho uma tela, no estilo splash, que gostaria que aparecesse para o usuário toda vez que alguma ação demorada executar, como por exemplo, uma consulta no banco (considere um banco na web, acessado pela maquina do cliente que possui link de 1 MB - isso chega a levar de 2 a 7 segundos pra completar cada ação- :frowning: )
A splashScreen funciona perfeitamente sozinha, porém quando chamo ela dentro de outro frame, a tela aparece, junto com a label que criei, mas a barra não, e quando a execução da minha operação no banco termina é que a barra aparece e começa e se mover (estou usando setIndeterminate(true))

Tentei de outras formas também, como criar uma progressBar diretamente no meu form, mas ocorre o mesmo, ela só inicia a execução depois que a consulta no banco já terminou, o que não adianta muito, rs.

Abaixo o código da splash screen, lembrando que ela funciona perfeitamente se for chamada sozinha:

public class waitScreen extends JWindow {


    public waitScreen() {
        JPanel content = (JPanel) getContentPane();
        content.setBackground(Color.white);

        final JProgressBar barra = new JProgressBar();
        int width = 350;
        int height = 150;
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (screen.width - width) / 2;
        int y = (screen.height - height) / 2;
        setBounds(x, y, width, height);


        Label label = new Label("Aguarde!!");
        content.add(label, BorderLayout.SOUTH);
        content.add(barra, BorderLayout.CENTER);
        Color verm = new Color(156, 20, 20, 255);
        content.setBorder(BorderFactory.createLineBorder(verm, 1));
        setVisible(true);
        
        SwingUtilities.invokeLater(new Runnable(){
   
            public void run() {

                barra.setIndeterminate(true);

            }
        });
        


    }


    public static void main(String[] args) {
        new waitScreen();
    }
}

A chamada da minha tela estou realizando antes de chamar o método que conecta no banco, como no exemplo abaixo:

new waitScreen();
meuMetodoDemorado();

Note que ainda não estou preocupado com o fechamento da tela, apenas quero fazer ela aparecer na tela enquanto meu método executa.

Como comentei, tentei criar a progressBar diretamente no meu form, e criei uma Thread para dispertá-la, mas ocorre o mesmo, ela só inicia quando a execução do meu método termina.

Tentei criando actionListener, Thread (propriamente dita) e invokeLater mas nada mudou.

Se alguém tiver alguma luz, ou souber de alguma forma mais fácil de deixar essa barrinha visível enquanto algo executa eu ficarei grato.

Abraços

3 Respostas

J

Recentemente precisei gerar uma barra de progresso para a geração de alguns arquivos de exportação.
Esta barra está no meu painel mesmo, só que ao disparar a ação de exportação é realizada uma busca no bd e esta busca lança um "painel sobreposto" onde o usuário fica impossibilitado de realizar qualquer ação.

Para atualizar esta progress bar também penei e só consegui usando uma thread dentro da outra.
Por motivos empresariais, não posso postar o código, mas é mais ou menos assim:

void acaoGerar(parametros){

        jpbarArquivos.setValue(0);
        
        for (int barra = 0; barra < dias; barra++) {
            // dispara a thred da busca
            // no retorno, chama o metodo retornoGerar();
        }
}

void retornoGerar(parametros){
        
        new Thread(new Runnable() {

            @Override
            public void run() {
                geraArquivoFisico(parametros);
            }
        }).start();
}


void geraArquivoFisico(parametros) {
      // instrucoes para gerar o arquivo
      // gera o arquivo, bla bla bla


        EventQueue.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                // calcula o pct
                jpbarArquivos.setValue((int) perc);
                
            }
        });
}

Espero que isso te ajude de alguma forma.

J

Outra forma que você pode tentar, obviamente adaptando a sua estrutura de código.

public class TestePBar extends JFrame{

	private JButton btnNewButton;
	private JProgressBar progressBar;
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			
			@Override
			public void run() {
				try {
					TestePBar frame = new TestePBar();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	
	public TestePBar() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		btnNewButton = new JButton("Executar");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				new Tarefa().execute();
			}
		});
		getContentPane().setLayout(new GridLayout(0, 1, 0, 0));
		getContentPane().add(btnNewButton);
		
		JScrollPane scrollPane = new JScrollPane();
		getContentPane().add(scrollPane);
		
		progressBar = new JProgressBar(0);
		progressBar.setStringPainted(true);
		scrollPane.setViewportView(progressBar);
	}


	
	
	class Tarefa extends SwingWorker<String, Integer>{

		public Tarefa() {
			btnNewButton.setEnabled(false);
		}
		
		@Override
		protected String doInBackground() throws Exception {
			
			for (int i = 0; i < 100; i++) {
				Thread.sleep(300);
				publish(i);
			}
			return "Processado.";
		}
		
		@Override
		protected void process(List<Integer> chunks) {
			progressBar.setValue((int) chunks.get(0).intValue());
		}
		
		@Override
		protected void done() {
			
			btnNewButton.setEnabled(true);
		}
		
	}
}
Z

Caro jhaga,
Somente o fato de você ter dito que criou uma Thread dentro de outra Thread já me deu a luz que precisava :slight_smile:
Pra revolver meu problema foi relativamente simples, eu modifiquei meu método do banco para Thread, conforme abaixo:

public void deletaItemPedido(final int item, int seq){
    final String query = "DELETE from PedidoItens WHERE codPed = " + item + " AND seqItem = " + seq;
    final BD  conn = new BD();
    new Thread(){   
    @Override
    public void run(){
    try {
    Statement stm = conn.criaConexao().createStatement();
    stm.execute(query);
    updateTable(item);
    }
    catch(SQLException ex){
    JOptionPane.showMessageDialog(null, "Erro ao remover!!");
    }
    }}.start();
    }

Agora tanto a telinha com a barra quanto a barra no meu form funcionaram exatamente do jeito que estavam, a única mudança mesmo foi colocar minha operação de banco como Thread, espero que isso não me gere nenhum outro problema, mas de qualquer forma a princípio funcionou :).

Abaixo a chamada da telinha no meu botão (Remover)

private void jButtonRemoverItemActionPerformed(java.awt.event.ActionEvent evt) {                                                   

        if (jTableVenda.getSelectedRowCount()==0){
            JOptionPane.showMessageDialog(this, "Selecione uma linha para deletar!!");
        
        }
        
        if(jTableVenda.getSelectedRowCount()>0){
        int opt = JOptionPane.showConfirmDialog(this, "Deseja realmente deletar este item?", "Atenção!!!",JOptionPane.YES_NO_OPTION);
        
        if (opt == JOptionPane.YES_OPTION){   
        String seqValor = (String)jTableVenda.getValueAt(jTableVenda.getSelectedRow(),0);
        int seq = Integer.valueOf(seqValor);
        wait.setVisible(true);
        deletaItemPedido(Integer.valueOf(jTextFieldPed.getText()), seq);
       
        }
        
        if (opt==JOptionPane.NO_OPTION){}
        
        
        }

Da forma acima está chamando a telinha normalmente.

Muito obrigado pela ajuda, grande abraço!

Criado 22 de janeiro de 2013
Ultima resposta 22 de jan. de 2013
Respostas 3
Participantes 2