Выбор нескольких ячеек в Swing JTable - PullRequest
0 голосов
/ 26 октября 2011

Я хочу предоставить возможность редактирования нескольких ячеек в JTable: двойной щелчок по-прежнему будет редактировать значение в выбранной ячейке (стандартное поведение), а щелчок правой кнопкой мыши должен открыть всплывающее меню с записью «Редактировать выбранные ячейки».".

Когда пользователь нажимает эту запись меню, последняя ячейка в выбранном диапазоне становится редактируемой.Другие выбранные ячейки остаются выделенными.Затем они записывают новое значение и, когда издание завершено (обычно нажатием Enter), все выбранные ячейки получают это значение.

Для простоты предположим, что все ячейки содержат одинаковые типы значений,скажем, целые числа.

Вот код, который показывает всплывающее диалоговое окно, чтобы начать:

table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
table.addMouseListener(new MouseAdapter() {
    @Override
    public void mousePressed(MouseEvent e) {
        if (e.isPopupTrigger()) {
            doPop(e);
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (e.isPopupTrigger()) {
            doPop(e);
        }
    }

    private void doPop(MouseEvent e) {
        MultiEditPopUp menu = new MultiEditPopUp(tblRanges);
        menu.show(e.getComponent(), e.getX(), e.getY());
    }
});


class MultiEditPopUp extends JPopupMenu {
    JMenuItem menuItem;

    MultiEditPopUp(JTable table) {
        menuItem = new JMenuItem("Edit selected");
        menuItem.setAction(new BulkEditAction(table));
        add(menuItem);
    }
}

class BulkEditAction extends AbstractAction {
    private final JTable table;

    public BulkEditAction(JTable table) {
        this.table = table;
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        // TODO: let the user edit the last cell, and then apply to the others
    }
}

Как я могу сделать такую ​​вещь?

Ответы [ 2 ]

2 голосов
/ 26 октября 2011

все еще не совсем уверен, в чем проблема. Основной подход будет

  • сохранить выбранные ячейки
  • разрешить пользователю редактировать один из них
  • в конце, возьмите отредактированное значение и установите его для всех ранее сохраненных ячеек

Единственная сложная часть, которую я вижу, это обнаружение «в конце» (потому что жизненный цикл редактирования не слишком четко определен). Некоторый фрагмент кода

public class BulkEditAction extends AbstractAction {
    JTable table;
    List selectedCells;

    public BulkEditAction(JTable table) {
        this.table = table;
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {

        // store, here rows only, refine for cell selection
        selectedCells = Arrays.asList(table.getSelectedRows());
        final int rowToEdit =  // ...
        final int columnToEdit = // ...
        table.editCellAt(rowToEdit, columnToEdit);
        CellEditorListener l = new CellEditorListener() {

            @Override
            public void editingStopped(ChangeEvent e) {
                ((AbstractCellEditor) e.getSource()).removeCellEditorListener(this);
                propagateEditedValue(rowToEdit, columnToEdit);

            }

            @Override
            public void editingCanceled(ChangeEvent e) {
                ((AbstractCellEditor) e.getSource()).removeCellEditorListener(this);
            }
        };
        table.getCellEditor().addCellEditorListener(l);
    }

    private void propagateEditedValue(final int row, final int column) {
        // need to invoke to be sure that the table has updated itself after
        // editingStopped
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // foreach selectedCell (with coordinates selectedRow/-column
                table.setValueAt(table.getValueAt(row, column), selectedRow, selectedColumn);
            }
        });
    }
}
0 голосов
/ 28 марта 2018

Я бы расширил JTable для создания MultiCellEditJTable

public class MultiCellEditJTable extends JTable{

    public MultiCellEditJTable(){
        setColumnSelectionAllowed(true);
        getSelectionModel().setSelectionMode(DefaultListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }


    @Override
    public Component prepareEditor(TableCellEditor editor, int row, int column){
        Component component = super.prepareEditor(editor, row, column);

        if(component instanceof JTextField){
            JTextField textField = (JTextField)component;
            textField.selectAll();
        }

        return component;
    }


    @Override
    public void editingStopped(ChangeEvent e){
        int editingRow = getEditingRow();
        int editingColumn = getEditingColumn();

        super.editingStopped(e);

        if(1 < getSelectedRowCount() && 1 == getSelectedColumnCount() && editingColumn == getSelectedColumn()){
            Object value = getValueAt(editingRow, editingColumn);
            Arrays.stream(getSelectedRows()).filter(row->row != editingRow).forEach(row->
              setValueAt(value, row, editingColumn)
            );
        }
    }
}

Когда выбрано несколько строк одного столбца и редактирование завершено, для всех выбранных ячеек устанавливается значение, полученное в результате редактирования.

В качестве дополнительного бонуса я сделал редактор selectAll, чтобы обеспечить функцию простого ввода желаемого значения после выбора диапазона ячеек.В противном случае сначала нужно вернуться на текущее значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...