Alterar text de JButton de outra classe

1 resposta
V

Olá,

Em um aplicativo desktop, tenho a classe inicial com o jButton de nome btnSincronizar. Após clicar nele, é chamada outra classe que implementa runnable de nome SincronizarDados. Preciso que assim que finalize o processo desta classe chamada, o botão volte a ficar ativo e o text volte ao que era: "Sincronizar".

public class Principal extends javax.swing.JFrame {
    public Principal() {
        setExtendedState(MAXIMIZED_BOTH);
        initComponents();
    }
...
    private void initComponents() {

        jFrame1 = new javax.swing.JFrame();
...
        btnSincronizar = new javax.swing.JButton();
...
    public JButton getBtnSincronizar() {
        return btnSincronizar;
    }

    public void setBtnSincronizar(JButton btnSincronizar) {
        this.btnSincronizar = btnSincronizar;
    }
...
    private void btnSincronizarActionPerformed(java.awt.event.ActionEvent evt) {                                            
        SincronizarDados sincronizarDados = new SincronizarDados();
        Thread threadSincronizarDados = new Thread(sincronizarDados);
        threadSincronizarDados.start();
        this.btnSincronizar.setText("Sincronizando");
        this.btnSincronizar.setEnabled(false);
    }
public class SincronizarDados implements Runnable {

...
    @Override
    public void run() {
        atualizaTabelaClientes();
    }
...
    public void atualizaTabelaClientes() {
           try {

            ProgressMonitor pm = new ProgressMonitor(null, "Iniciando...", "Inicializando sincronização dos dados...", 0, 0);

            ARRAYOFSTRUCTCLI resultClientes = listaclientes(Acesso.getInstance().getCodigo(), "", "", "", "", "");
...

Como fazer para voltar o JButton ao que era antes? Não funcionou quando fiz da forma abaixo, por se tratar de thread acredito apareceu rapidamente "Soncronizando" e antes da rotina chamada terminar já voltou para "Sincronizar" e a habilitação do botão:

private void btnSincronizarActionPerformed(java.awt.event.ActionEvent evt) {                                            
        this.btnSincronizar.setText("Sincronizando");
        this.btnSincronizar.setEnabled(false);
        SincronizarDados sincronizarDados = new SincronizarDados();
        Thread threadSincronizarDados = new Thread(sincronizarDados);
        threadSincronizarDados.start();
        this.btnSincronizar.setText("Sincronizar");
        this.btnSincronizar.setEnabled(true);
    }

1 Resposta

lucasirc

vicentedepaula,

Antes de tudo:

  1. o swing trabalha na EDT( Event Dispatch Thread), qualquer operacao com os componentes do swing devem ser feitas dentro dessa thread
public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setSize(200, 200);
        frame.setVisible(true);
    }

na linha 2 o JFrame é instanciado, nesse momento já são criado as threads utilizadas pelo swing para eventos, atualizacoes de telas.
o codigo funciona, mas seguindo a regra que disse acima está errado. qual a forma correta?

Utilize

SwingUtilities.invokeAndWait( seu Runnable ); 
ou
SwingUtilities.invokeLater(seu Runnable);

verifica o javadoc pra ver qual te atende melhor sempre que precisar executar uma thread na EDT

SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                   JFrame frame = new JFrame();
        frame.setSize(200, 200);
        frame.setVisible(true);
            }
        });
  1. o swing só atualiza a tela no final do evento
//mandei o swing pintar sincronizando no swing button
        this.btnSincronizar.setText("Sincronizando");
        this.btnSincronizar.setEnabled(false);
        SincronizarDados sincronizarDados = new SincronizarDados();
        Thread threadSincronizarDados = new Thread(sincronizarDados);
        threadSincronizarDados.start();
        //mandei ele pintar "sincronizar" no swing button <- perceba que aqui ainda o swingo não mandou pintar seu botao com o texto "sincronizando"        
        this.btnSincronizar.setText("Sincronizar");
        this.btnSincronizar.setEnabled(true);
        //fim evento
        ...
        //swing manda pintar componentes

entao, como fazer atualizar tela, fazer processamento demorado e atualizar apos termina o processamento?
pensando nisso… foi criado o SwingWorker
ele executa o seu processamento fora da EDT, e apos terminar o processamento executa outro metodo dentro da EDT

private void btnSincronizarActionPerformed(java.awt.event.ActionEvent evt) {  
  this.btnSincronizar.setText("Sincronizando");
  this.btnSincronizar.setEnabled(false);
   SwingWorker sw =  SwingWorker<String, Object> {

       //É executado fora da EDT, aqui fica o seu processamento demorado
       // deve realizar atualizacao de tela  nesse metodo utilizando process (não entrarei em detalhes nesse topico)
       @Override
       public String doInBackground() {
              SincronizarDados sincronizarDados = new SincronizarDados();
             sincronizarDados.atualizaTabelaClientes();

             String saida = "ok";
             return saida;
       }


       //Aqui é executado dentro da EDT apos terminar o processamento
       //Voce pode atualizar tela nesse metodo
       @Override
       protected void done() {
           try { 
                /*metodo get recebe o retorno de doInBackground(), é importante sempre chamar ele, mesmo que nao haja retorno ou não precise, voce pode perder alguma "exception" que ocorreu no doBackGround */
               String saida =  get();
                
                this.btnSincronizar.setText("Sincronizar");
                this.btnSincronizar.setEnabled(true);
                this.btnSincronizar.setSelected(true);

           } catch (Exception ex) {
                  ex.getCause() // exception que ocorreu
           }
       }
   }
 
   sw.execute();

o primeiro tipo na declaração em SwingWorker<String, Object>, será o tipo de retorno do metodo doInBackground()

de uma olhada em http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html pra entender melhor

qualquer duvida…

abraços

Criado 21 de março de 2013
Ultima resposta 22 de mar. de 2013
Respostas 1
Participantes 2