簡體   English   中英

Swing JTable中的多單元選擇

[英]Multi-cell selection in a Swing JTable

我想為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
    }
}

我該怎么辦?

仍不太確定問題是什么。 基本方法是

  • 存儲選定的單元格
  • 讓用戶編輯其中一個
  • 最后,獲取編輯后的值並將其設置為以前存儲的所有單元格

我看到的唯一棘手的部分可能是“在最后”檢測(因為編輯的生命周期沒有過分定義)。 一些代碼片段

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

我會擴展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提供了在選擇一系列單元格后能夠輸入所需值的功能。 否則,必須首先對當前值進行退格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM