Delete only lines with selected checkbox in a Jtable

Asked

Viewed 332 times

0

How to delete from a JTable lines that are marked in a Checkbox that is in a table cell? I am using AbstractTableModel.

The code I was able to create, erases only part of the selected records, always leaves some.

I created a simple code with the simulation of the problem:

Testing

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;    
public class Teste extends JFrame{
       //MAIN METHOD
      public static void main(String[] args)
      {

           EventQueue.invokeLater(new Runnable()
           {
               public void run()
               {
                   //INITIALIZE JFRAME FORM
                   teste.Teste form=new teste.Teste();
                   form.setVisible(true);;
               }
           });

      }

      private JTextField txtId;

      TesteTableModel tableModel = new TesteTableModel();
      private final JTable table;

      //CONSTRUCTOR
      public Teste()
      {
            setLayout(null);
            setSize(794, 548);

            JLabel lblListaDePendencias = new JLabel("Lista de Pend\u00EAncias:");
            lblListaDePendencias.setBounds(10, 11, 120, 14);
            add(lblListaDePendencias);

            JPanel panel = new JPanel();
            panel.setBounds(10, 31, 774, 380);
            add(panel);
            panel.setLayout(null);

            table = new JTable(tableModel);
            table.setBounds(0, 0, 774, 380);
            panel.add(table);

            JScrollPane scrollPane = new JScrollPane(table);
            scrollPane.setBounds(0, 0, 774, 380);
            panel.add(scrollPane);

            table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);

            JButton btnRemoverPendencias = new JButton("Remover");
            btnRemoverPendencias.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    tableModel.deletarLinhas();
                }
            });
            btnRemoverPendencias.setBounds(10, 422, 157, 23);
             add(btnRemoverPendencias);

             TesteModel t1 = new TesteModel();
             t1.setSelecionado(false);
             t1.setNome("Pedro");

             TesteModel t2 = new TesteModel();
             t2.setSelecionado(false);
             t2.setNome("Maria");

             TesteModel t3 = new TesteModel();
             t3.setSelecionado(false);
             t3.setNome("João");

             TesteModel t4 = new TesteModel();
             t4.setSelecionado(false);
             t4.setNome("Helena");

             TesteModel t5 = new TesteModel();
             t5.setSelecionado(false);
             t5.setNome("Lúcia");

             tableModel.addRow(t1);
             tableModel.addRow(t2);
             tableModel.addRow(t3);
             tableModel.addRow(t4);
             tableModel.addRow(t5);

      }
    }

model class

import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;

    public class TesteModel {
        private Boolean selecionado;
        private String nome;

        public Boolean getSelecionado() {
            return selecionado;
        }

        public void setSelecionado(Boolean selecionado) {
            this.selecionado = selecionado;
        }

        public String getNome() {
            return nome;
        }

        public void setNome(String nome) {
            this.nome = nome;
        }

    }

Tablemodel class

public class TesteTableModel extends AbstractTableModel {


    private List<TesteModel> dados = new ArrayList<>();
    private String[] colunas = {"Selecionar", "Nome"};


    public Class<?> getColumnClass(int columnIndex) {
        return columnIndex == 0 ? Boolean.class : super.getColumnClass(columnIndex);
    }

    @Override
    public String getColumnName(int column){
        return colunas[column];
    }

    @Override
    public int getColumnCount() {
        return colunas.length;
    }

    @Override
    public int getRowCount() {
        return dados.size();
    }

    @Override
    public Object getValueAt(int linha, int coluna) {
        switch(coluna){
            case 0:
                return dados.get(linha).getSelecionado();
            case 1:
                return dados.get(linha).getNome();
        }

        return null;
    }

    public void setValueAt(Object valor, int linha, int coluna) {
        TesteModel tm = dados.get(linha);
        switch (coluna) {
        case 0:
            tm.setSelecionado(new Boolean((Boolean) valor));
            break;
        }
        fireTableDataChanged();
    }

    public void addRow(TesteModel tm) {
        this.dados.add(tm);
        this.fireTableDataChanged();    
    }

    public void removeRow(int linha){
        this.dados.remove(linha);
        this.fireTableRowsDeleted(linha, linha);
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        switch (columnIndex) {
            case 0:
                    return true;
            default:
                return false;
        }
    }

    public void deletarLinhas() {
        for (int i = 0; i < dados.size(); i++) {
            if(dados.get(i).getSelecionado()) {
                dados.remove(i); //Remove o aluno da lista
                fireTableRowsDeleted(i, i); //Informa a tabela
            }
        }

    }
}
  • Lys, always add the Imports together with the code, they are part too.

  • Right, added.

1 answer

2


The recommendation is that by massively deleting lines from a JTable, is done in a decreasing way in the indexes, because at each deletion, the Dice of the list of objects of her is updated, and this causes some bugs as this of not deleting all items.

Change to:

public void deletarLinhas() {
    
    for (int i = getRowCount() - 1; i >= 0; i--) {

        if (dados.get(i).getSelecionado()) {
            removeRow(i);
        }
    }
}

Another tip is not to duplicate actions, your class already has a method of removing individual lines, which is the removeRow(), If you want to remove line by line, just call this method and pass the index to it. The same tip goes for the list size, always try to opt for the most abstract form possible, it facilitates not only understanding and maintenance, but avoids adding duplicate and unnecessary code.

With this modification, the code works normally:

inserir a descrição da imagem aqui


Another tip is this method isCellEditable(), Creating a switch just to validate a condition is again a waste of code. This can be simplified in just one line, without ceasing to be readable:

public boolean isCellEditable(int rowIndex, int columnIndex) {
        
    return columnIndex == 0; 
}

It is also worth mentioning the recommendation below:

Avoid using absolute layout, unless it is of extreme necessity and you know the consequences of it, because absolute layout makes it difficult to maintain the screen and makes your application look different depending on the monitor and resolution that is running.

There are several layouts so you don’t have to worry about positioning or manually organizing components. Not to mention that using layouts makes your code easier to maintain than inserting a lot of setbounds, and if you need to change the position of any component, in the absolute layout, you will have to reposition all manually.

  • Wow, so simple! I had already tried several approaches but not decreasing. Thank you very much for this and also for the improvement tips, I will take them all into consideration.

  • @Lys dispose :)

Browser other questions tagged

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