Update Jtable after each data change in a cell

Asked

Viewed 3,495 times

1

I’m using java where I have a window and in it a JTable.

I run a method where you will read the data from this Jtable and update a column, cell by cell, of this Jtable. The problem is that it runs the method normally by running the looping, but updates the column(all cells) only at the end. I would like you to update the cell line by line and not everything only at the end.

Follows code:

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


        SMSMultiploBean smsb = new SMSMultiploBean();
        SMSMultiploDAO smsd = new SMSMultiploDAO();

        int i;
        int linha = 0;
        int totenviados = 0;

        for(i = 0;i<TblDadosSMS.getModel().getRowCount();i++){


            smsb.setDdd((String) TblDadosSMS.getValueAt(linha, 4));
            smsb.setTelefone((String) TblDadosSMS.getValueAt(linha, 5));
            smsb.setMensagem((String) TblDadosSMS.getValueAt(linha, 6));
            smsb.setLinha((int)TblDadosSMS.getValueAt(linha,8));


            Date data= JData.getDate();
            Format ff = new SimpleDateFormat("ddMMyyyy");
            String datastring = ff.format(data);

            smsb.setData(datastring);


                try {            

                    String retorno = smsd.EnviaSms(smsb);

                     //retorno falando se o SMS foi enviado ou não

                    TblDadosSMS.setValueAt(retorno, i, 7);

                    //TblDadosSMS.firePropertyChange(retorno, i, i);

                    Pbar.setMinimum(0);
                    Pbar.setMaximum(Integer.parseInt((LblTotal.getText())));
                    Pbar.setValue(i+1);



                    if (retorno.equals("Enviado")){
                      totenviados += 1;
                      LblEnviados.setText(Integer.toString(totenviados));
                    }

                 } catch (Exception ex) {
                     Logger.getLogger(FrmSMSSimultaneo.class.getName()).log(Level.SEVERE, null, ex);
                     JOptionPane.showMessageDialog(this, "Erro: "+ex);
                 }
                     linha++;


       }   


    }                                         

Window before executing method: inserir a descrição da imagem aqui

Window after executing code:

inserir a descrição da imagem aqui

Below is code for popular table:

private void CarregaDadosPlanilha() throws SQLException, IOException, ParseException, Exception {

    ExcelBean eb = new ExcelBean();
    ExcelDao ed = new ExcelDao();


    //data convertida para String
    Date data = JData.getDate();
    SimpleDateFormat formatador = new SimpleDateFormat("dd/MM/yyyy");  
    String novadata = formatador.format(data);  


    //conversão String para date
    String texto = novadata;  
    String formato = "dd/MM/yyyy";  
    Date dataobjeto = new SimpleDateFormat(formato).parse(texto);

    //System.out.println("Data tratada date: "+dataobjeto);  

    eb.setData(dataobjeto);

    List<ExcelBean> ListaDadosPlanilha = new ArrayList<ExcelBean>();

           // ListaDadosPlanilha = ed.CarregaExcel(eb);
     ListaDadosPlanilha = ed.LeExcel(eb);

            DefaultTableModel tbm = (DefaultTableModel) TblDadosSMS.getModel();

            //zera as linhas da tabela
            for (int i = tbm.getRowCount() - 1; i >= 0; i--) {
                tbm.removeRow(i);
            }
            int i = TblDadosSMS.getRowCount();
            /*
             * preenche a tabela
             */
               for (ExcelBean eb2 : ListaDadosPlanilha) {
                tbm.addRow(new String[1]);

                TblDadosSMS.setValueAt(eb2.getNome(), i, 0);
                TblDadosSMS.setValueAt(eb2.getServico(), i, 1);


                //data convertida para String
                Date dataexcel = JData.getDate();  
                SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy");  
                String datastring = f.format(dataexcel);  

                TblDadosSMS.setValueAt(datastring, i, 2);
                TblDadosSMS.setValueAt(eb2.getHorario(), i, 3);
                TblDadosSMS.setValueAt(eb2.getDdd(), i, 4);
                TblDadosSMS.setValueAt(eb2.getTelefone(), i, 5);

                eb2.setMensagem("Prezado(a): "+eb2.getNome()+
                    " , nao se esqueca que tem o servico: "+eb2.getServico()+" marcado para: "+novadata+
                    " as: "+eb2.getHorario());


                TblDadosSMS.setValueAt(eb2.getMensagem(), i, 6);


                TblDadosSMS.setValueAt(eb2.getLinha(),i,8);

                System.out.println("Linha célula form: "+eb2.getLinha());


              //System.out.println("linha jtable: "+eb2.getLinha());



                i++;
            }

               LblTotal.setText(Integer.toString(tbm.getRowCount()));
}
  • You are using your own Tablemodel or are using defaultTableModel in this table?

  • Rodrigo, when you create a question and need to supplement it, click [Edit] on the question and directly add the information to it. The field below is for answers.

  • Sorry Diego, I’m still getting the hang of it.

  • Sorry for the intrusion, but you have already tried to use a method that sends one by one, reading this one after the change and let automatically change (update) a second method and so on until you finish all?

1 answer

3


This is because you are running the loop and increasing progress within the Event Dispatch Thread(EDT), and that Thread will execute all the code that is on it before updating the container(Jframe, Jpanel, etc) and its components.

To update the table and progress to each row, you need to update the TableModel in a Thread parallel, and the best way to do this together with EDT is by using SwingWorker.

I’ve worked out a simple example just to demonstrate the workings of SwingWorker with the EDT, is commented the main parts related to the functioning of progress:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import java.util.List;

public class ProgressWithSwingWorker extends JFrame {

    private JButton btnChecar;
    private JProgressBar progressBar;
    private JScrollPane ScrollPane;
    private JTable tabela;

    public ProgressWithSwingWorker() {
        initComponents();
    }

    private void initComponents() {

        ScrollPane = new JScrollPane();
        btnChecar = new JButton();
        progressBar = new JProgressBar();

        String[] columns = {"coluna 1", "coluna 2", "coluna 3", "coluna 4"};
        Object[][] data = new Object[][]{
            {null, null, null, null},
            {null, null, null, null},
            {null, null, null, null},
            {null, null, null, null},
            {null, null, null, null},
            {null, null, null, null}
        };

        DefaultTableModel model = new DefaultTableModel(data, columns) {
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                if (columnIndex == 3) {
                    return Boolean.class;
                } else {
                    return super.getColumnClass(columnIndex);
                }
            }
        };

        tabela = new JTable(model);

        ScrollPane.setViewportView(tabela);
        btnChecar.setText("Checar");
        //A "mágica" acontece na classe ChecarComSwingWorker
        btnChecar.addActionListener(new ChecarComSwingWorker());

        this.setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(ScrollPane, BorderLayout.NORTH);
        this.add(btnChecar, BorderLayout.CENTER);
        this.add(progressBar, BorderLayout.SOUTH);

        pack();
    }

    public static void main(String args[]) {

        EventQueue.invokeLater(() -> new ProgressWithSwingWorker().setVisible(true));
    }

    class ChecarComSwingWorker implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            final int totalRows = tabela.getModel().getRowCount();
            progressBar.setMaximum(totalRows);
            progressBar.setMinimum(0);
            //passei parametros para facilitar o entendimento
            //- o primeiro é o retorno do doInBackground(não foi necessario uso neste exemplo)
            //- o segundo é o tipo do valor usado entre o publish e o process
            SwingWorker<Object, Integer> worker = new SwingWorker<Object, Integer>() {

                //este método é que executa em uma Thread paralela
                //todo processamento pesado que deve ser executado
                //fora da EDT, deve ser executado aqui 
                @Override
                protected Object doInBackground() {
                    for (int i = 0; i < totalRows; i++) {
                        try {
                            Boolean status = (Boolean) tabela.getModel().getValueAt(i, 3);
                            status = status == null ? true : !status;
                            tabela.getModel().setValueAt(status, i, 3);
                            //este método é que atualiza a barra de progresso
                            //passando cada iteração para o método process
                            publish(i);
                            Thread.sleep(400);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    return null;
                }

                //este método é que recebe o que é passado no publish
                //e atualiza a barra de progresso na EDT
                @Override
                protected void process(List<Integer> chunks) {
                    int valueRecent = chunks.get(chunks.size() - 1);
                    progressBar.setValue(valueRecent + 1);
                }

                //só é executado quando o doInBackground termina
                //o processamento
                @Override
                protected void done() {
                    progressBar.setValue(0);
                }
            };

            worker.execute();
        }
    }
}

And the result is:

gif de execução do código

Below are some links regarding the use of SwingWorker:

11.5 - Threading and competition difficulties - Caelum

Working with Swingworker in Java - Devmedia

Capture exceptions in swingworker execution

Pass the execution of a given method to another as argument

  • Diego, when writing Tbldadossms.getModel(). fireTableDataChanged(); the NETBEANS identifies as an error. I’m using these libraries "import javax.swing.table.Abstracttablemodel; import javax.swing.table.Defaulttablemodel model;"

  • I followed the devmedia tutorial and it worked perfectly. Thank you. Problem solved

  • @Rodrigostortideoliveira if the answer helped you, it would be interesting to mark it as accepted, so it will serve as reference for other users. :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.