Выбор нескольких строк в JTable - PullRequest
5 голосов
/ 24 декабря 2010

У меня есть JTable, у которого есть один столбец с текстом, который нельзя редактировать, а второй столбец - это флажок, отображающий логические значения .... Теперь я хочу, чтобы пользователь выбирал несколько строк и снимал всеодин из выбранных флажков, тогда все выбранные флажки должны быть сняты и наоборот.

Ответы [ 4 ]

14 голосов
/ 25 декабря 2010

Используя пример @ Hovercraft и советы @ camickr, в приведенном ниже примере показан подходящий пользовательский интерфейс.Хотя он использует кнопки, SelectionAction также подойдет для меню или всплывающего окна.

Check A Bunch

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();
            }
        });
    }
}
4 голосов
/ 24 декабря 2010

Проблема в том, что при нажатии на флажок, чтобы изменить значение флажка, выбор всех строк будет потерян.Таким образом, вам может потребоваться щелкнуть правой кнопкой мыши, чтобы отобразить всплывающее меню, содержащее значения выбора / отмены выбора.

Затем вы можете использовать table.getSelectedRows (), чтобы получить индексы всех выбранных строк, которые нужно обновить.

2 голосов
/ 24 декабря 2010

Я согласен с Романом, что его идея сработает, если вы используете поле класса для хранения минимального и максимального выбора. Например:

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();
            }
        });
    }
}
2 голосов
/ 24 декабря 2010

Вы можете получить интервал выбора с кодом, подобным следующему:

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

Затем, когда установлен один флажок (прослушать ItemEvent), вы должны перейти от minSelectedRow к maxSelectedRow и изменить состояние флажков. Вот и все.

...