Delete only rows with checked checkbox in a JTable

0

How do I delete a row from a% w / o of the lines that are marked in a CheckBox that is in a table cell? I'm using JTable .

The code I was able to create, just delete some of the selected records, there is always some left over.

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

Test

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);

      }
    }

class model

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
            }
        }

    }
}
    
asked by anonymous 01.11.2018 / 19:24

1 answer

2

The recommendation is that by mass deleting lines of a JTable , it is done in a decreasing way in the indexes, because with each deletion, the index of its list of objects is updated, and this causes some bugs like 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 to not duplicate actions, your class already has a method of removing individual rows, which is removeRow() , if you want to remove row by row, just call this method and pass the index to it. The same tip applies to the size of the list, always try to choose the most abstracted way possible, this facilitates not only understanding and maintenance, but also avoiding duplicate and unnecessary code addition.

With this modification, the code works normally:

AnothertipisthisisCellEditable()method,creatingaswitchjusttovalidateaconditionisagainawasteofcode.Thiscanbesimplifiedinjustoneline,whileremaininglegible:

publicbooleanisCellEditable(introwIndex,intcolumnIndex){returncolumnIndex==0;}

Alsonotetherecommendationbelow:

  

Avoidusingabsolutelayoutunlessyouareindireneedandknowtheconsequences,becauseabsolutelayoutmakesitdifficulttomaintainthescreenandmakeyourapplicationlookdifferentdependingonthemonitorandresolutionbeingexecuted.

    

Thereareseveral layouts managers for you to you do not have to worry about manual positioning or organization of components. Not to mention that the use of layouts makes your code easier to maintain than inserting a lot of setbounds , and in case you need to change the position of any component, in the absolute layout, you will have to reposition them all manually.

    
01.11.2018 / 19:48