Selección de varias filas en JTable

Resuelto sasidhar asked hace 13 años • 4 respuestas

Tengo una JTable, que tiene una columna que es texto que no es editable y la segunda columna es una casilla de verificación que muestra valores booleanos... Ahora lo que quiero es, cuando el usuario selecciona varias filas y desmarca cualquiera de las casillas de verificación seleccionadas, todas las casillas de verificación bajo selección deben quedar desmarcadas y viceversa.

sasidhar avatar Dec 24 '10 21:12 sasidhar
Aceptado

Utilizando el ejemplo de @Hovercraft y los consejos de @camickr, el siguiente ejemplo muestra una interfaz de usuario adecuada. Aunque utiliza botones, SelectionActiontambién sería adecuado para un menú o ventana emergente.

comprobar un montón

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.DefaultListSelectionModel;
import javax.swing.table.DefaultTableModel;

/** @see http://stackoverflow.com/questions/4526779 */
public class CheckABunch extends JPanel {

    private static final int CHECK_COL = 1;
    private static final Object[][] DATA = {
        {"One", Boolean.TRUE}, {"Two", Boolean.FALSE},
        {"Three", Boolean.TRUE}, {"Four", Boolean.FALSE},
        {"Five", Boolean.TRUE}, {"Six", Boolean.FALSE},
        {"Seven", Boolean.TRUE}, {"Eight", Boolean.FALSE},
        {"Nine", Boolean.TRUE}, {"Ten", Boolean.FALSE}};
    private static final String[] COLUMNS = {"Number", "CheckBox"};
    private DataModel dataModel = new DataModel(DATA, COLUMNS);
    private JTable table = new JTable(dataModel);
    private DefaultListSelectionModel selectionModel;

    public CheckABunch() {
        super(new BorderLayout());
        this.add(new JScrollPane(table));
        this.add(new ControlPanel(), BorderLayout.SOUTH);
        table.setPreferredScrollableViewportSize(new Dimension(250, 175));
        selectionModel = (DefaultListSelectionModel) table.getSelectionModel();
    }

    private class DataModel extends DefaultTableModel {

        public DataModel(Object[][] data, Object[] columnNames) {
            super(data, columnNames);
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndex == CHECK_COL) {
                return getValueAt(0, CHECK_COL).getClass();
            }
            return super.getColumnClass(columnIndex);
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return column == CHECK_COL;
        }
    }

    private class ControlPanel extends JPanel {

        public ControlPanel() {
            this.add(new JLabel("Selection:"));
            this.add(new JButton(new SelectionAction("Clear", false)));
            this.add(new JButton(new SelectionAction("Check", true)));
        }
    }

    private class SelectionAction extends AbstractAction {

        boolean value;

        public SelectionAction(String name, boolean value) {
            super(name);
            this.value = value;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < dataModel.getRowCount(); i++) {
                if (selectionModel.isSelectedIndex(i)) {
                    dataModel.setValueAt(value, i, CHECK_COL);
                }
            }
        }
    }

    private static void createAndShowUI() {
        JFrame frame = new JFrame("CheckABunch");
        frame.add(new CheckABunch());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowUI();
            }
        });
    }
}
trashgod avatar Dec 24 '2010 22:12 trashgod

El problema es que cuando haces clic en una casilla de verificación para cambiar el valor de la misma, se perderá la selección de todas las filas. Por lo tanto, es posible que necesite hacer clic con el botón derecho del mouse para mostrar un menú emergente que contiene valores de selección/deseleccionación.

Luego puede usar table.getSelectedRows() para obtener los índices de todas las filas seleccionadas que necesita actualizar.

camickr avatar Dec 24 '2010 16:12 camickr

Puede obtener el intervalo de selección con un código similar a este:

table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
    public void valueChanged(ListSelectionEvent e) {
        minSelectedRow = ((DefaultListSelectionModel)e.getSource()).getMinSelectionIndex();
        maxSelectedRow = ((DefaultListSelectionModel)e.getSource()).getMaxSelectionIndex();
    }
});

Luego, cuando se marca una casilla de verificación (escuche ItemEvent), debe iterar desde a minSelectedRowy maxSelectedRowcambiar el estado de las casillas marcadas. Eso es todo.

Roman avatar Dec 24 '2010 14:12 Roman

Estoy de acuerdo con Roman en que su idea funcionaría si usara un campo de clase para mantener la selección mínima y máxima. Por ejemplo:

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

public class CheckABunch extends JPanel {
    private static final Object[][] DATA = {{"One", Boolean.TRUE}, {"Two", Boolean.FALSE},
        {"Three", Boolean.TRUE}, {"Four", Boolean.FALSE}, {"Five", Boolean.TRUE},
        {"Six", Boolean.FALSE}, {"Seven", Boolean.TRUE}, {"Eight", Boolean.FALSE}};
    private static final String[] COLUMNS = {"Number", "CheckBox"};
    private DefaultTableModel model = new DefaultTableModel(DATA, COLUMNS) {
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndex == 1) {
                return getValueAt(0, 1).getClass();
            }
            return super.getColumnClass(columnIndex);
        }
    };
    private JTable table = new JTable(model);
    private int minSelectedRow = -1;
    private int maxSelectedRow = -1;
    boolean tableModelListenerIsChanging = false;

    public CheckABunch() {
        add(new JScrollPane(table));

        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) {
                    return;
                }
                minSelectedRow = ((DefaultListSelectionModel) e.getSource()).getMinSelectionIndex();
                maxSelectedRow = ((DefaultListSelectionModel) e.getSource()).getMaxSelectionIndex();
            }
        });

        model.addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                if (tableModelListenerIsChanging) {
                    return;
                }                
                int firstRow = e.getFirstRow();
                int column = e.getColumn();

                if (column != 1 || maxSelectedRow == -1 || minSelectedRow == -1) {
                    return;
                }
                tableModelListenerIsChanging = true;
                boolean value = ((Boolean)model.getValueAt(firstRow, column)).booleanValue();
                for (int i = minSelectedRow; i <= maxSelectedRow; i++) {
                    model.setValueAt(Boolean.valueOf(value), i, column);
                }

                // *** edit: added two lines
                minSelectedRow = -1;
                maxSelectedRow = -1;

                tableModelListenerIsChanging = false;
            }
        });
    }

    private static void createAndShowUI() {
        JFrame frame = new JFrame("CheckABunch");
        frame.getContentPane().add(new CheckABunch());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}
Hovercraft Full Of Eels avatar Dec 24 '2010 16:12 Hovercraft Full Of Eels