![](/img/trans.png)
[英]Switch between row selection mode and single cell selection mode in Java/JFC 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.