Problema com Observer e atualização do JTextField

1 resposta
juceliohv

:D Bom dia a todos :!:

Tenho o seguinte problema.

Preciso criar um processo que é disparado por uma tela, porém a tela não pode ficar imóvel, tenho que informar o usuário sobre o andamento do processo através de uma barra de progresso e de mensagens que serão mostradas por um JTextField.

Criei um exemplo simples usando o pattern Observer, consigo atualizar o System.out.println no console, mas não consigo atualizar a tela em tempo de execução.

:( O que está errado?

Segue código da Tela Observer :
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Tela.java
 *
 * Created on 06/04/2011, 08:18:56
 */

package testethread;

import java.util.Observable;
import java.util.Observer;

/**
 *
 * @author juc
 */
public class Tela extends javax.swing.JFrame implements Observer{
    private Executor exec;

    /** Creates new form Tela */
    public Tela() {
        initComponents();
        exec = new Executor();
        exec.addObserver(this);

    }

    public void update(Observable o, Object arg){

        jTextField1.setText(exec.getLabel());
        if (exec.getSizeProc() != 0 ){
            jProgressBar1.setMaximum(exec.getSizeProc());
        }
        jProgressBar1.setValue(exec.getContador());
        System.out.println(exec.getLabel());
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jTextField1 = new javax.swing.JTextField();
        jProgressBar1 = new javax.swing.JProgressBar();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.setBackground(new java.awt.Color(255, 255, 255));

        jButton1.setText("Executar");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jTextField1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextField1ActionPerformed(evt);
            }
        });

        jProgressBar1.setStringPainted(true);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(6, 6, 6)
                        .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 370, Short.MAX_VALUE))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jButton1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(229, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>

    private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        exec.executa();        // TODO add your handling code here:
        
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Tela().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JTextField jTextField1;
    // End of variables declaration

}

Segue código da classe Observable:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package testethread;

import java.util.Observable;

/**
 *
 * @author juc
 */
public class Executor extends Observable {
    
    private Thread processo = null;

    private int contador;
    private String label;
    private static int sizeProc = 50000;

    public Executor(){
        
    }    
    

    public void run(){


        for (int i = 0; i < 5000; i++){
            this.setLabel("Iniciando");

            setChanged();
            notifyObservers(label);
            
        }


        for (int i = 0; i < 50000; i++){
            this.setContador(i);
            this.setLabel("Contando: " + i);

            setChanged();
            notifyObservers(label);
                        
        }

        for (int i = 0; i < 5000; i++){
            this.setLabel("Finalizando");

            setChanged();
            notifyObservers(label);
            
        }
        
    }

    public int getContador(){
        return this.contador;
    }

    public void setContador(int cont){
        this.contador = cont;
    }

    public String getLabel(){
        return this.label;
    }

    public void setLabel(String label){
        this.label = label;
    }

    public int getSizeProc(){
        return this.sizeProc;
    }

}

1 Resposta

Luiz_Gustavo

Olá!

Você tentou executar o processo em uma thread separada?
Pelo que entendi você está executando o processo a partir da tela, ou seja, a partir da mesma thread que a tela. Se o processo for demorado (como imagino que é, por usar um JProgressBar) a tela ficará “travada” até que o processo termine.

Neste link você encontra exemplo de como usar uma instância de Task para execução do processo:

http://download.oracle.com/javase/tutorial/uiswing/components/progress.html

Task is a subclass of javax.swing.SwingWorker. The Task instance does three important things for ProgressBarDemo:

  1. The instance invokes the doInBackground in a separate thread. This is where the long-running task is actually executed. Using a background thread instead of the event-dispatching thread prevents the user interface from freezing while the task is running.
  2. When the background task is complete, the instance invokes the done method in the event-dispatching thread.
  3. The instance maintains a bound property, progress, that is updated to indicate the progress of the task. The propertyChange method is invoked each time progress changes.

Abraço!

Criado 6 de abril de 2011
Ultima resposta 6 de abr. de 2011
Respostas 1
Participantes 2