【问题标题】:How to set CellEditor in JTable?如何在 JTable 中设置 CellEditor?
【发布时间】:2018-12-23 21:41:35
【问题描述】:

我想为JTable 中的一个单元格设置CellEditorJComboBox。它是一个单元格而不是所有列,我在 JDK 中找不到名为 Cell 的类。

此代码无法解决我的要求。

table.getColumnModel().getColumn(columnIndex).setCellEditor(new DefaultCellEditor(new JComboBox));  

【问题讨论】:

    标签: java swing jtable tablecelleditor


    【解决方案1】:

    这很简单。你只需要覆盖JTable的方法getCellRenderer。这是一个例子。

    import java.awt.Component;
    import java.awt.font.TextAttribute;
    import java.util.Collections;
    
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.WindowConstants;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableCellRenderer;
    
    @SuppressWarnings("unchecked")
    public class TableRendererTest {
    
        public static void main(String[] args) {
            JFrame frm = new JFrame("Renderer test");
            DefaultTableModel model = new DefaultTableModel(new String[] {"First", "Second", "Third" }, 3);
            model.setValueAt("First row cell", 0, 1);
            model.setValueAt("Striked out string", 1, 1);
            model.setValueAt("Last row cell", 2, 1);
    
            TableCellRenderer strikeOutRenderer = new StrikeOutRenderer();
            // table with strike-out renderer (last cell is not stroked out)
            // create a custom table with possibility to change renderer for a single cell.
            JTable tbl = new JTable(model) {
                @Override
                public TableCellRenderer getCellRenderer(int row, int column) {
                    if (row == 1 && column == 1) {
                        return strikeOutRenderer;
                    }
                    return super.getCellRenderer(row, column);
                }
            };
            frm.add(new JScrollPane(tbl));
    
            frm.pack();
            frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frm.setLocationRelativeTo(null);
            frm.setVisible(true);
        }
    
        private static class StrikeOutRenderer extends DefaultTableCellRenderer {
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                    int column) {
                Component res = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                res.setFont(res.getFont().deriveFont(Collections.singletonMap(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON)));
                return res;
            }
        }
    }
    

    这里是完整解决方案的代码,因此您可以在任何地方使用表格,并且可以为任何单元格定义渲染器。

    // defined in JCellStyleTable.java
    public class JCellStyleTable extends JTable {
    
    
        private final Map<Cell, TableCellRenderer> renderersMap = new HashMap<>();
    
        private final Map<Cell, TableCellEditor> editorsMap = new HashMap<>();
    
        public JCellStyleTable() {
            super();
        }
    
        public JCellStyleTable(TableModel dm) {
            super(dm);
        }
    
        public void putRenderer(Cell cell, TableCellRenderer renderer) {
            renderersMap.put(Objects.requireNonNull(cell), renderer);
        }
    
        public TableCellRenderer getRenderer(Cell cell) {
            return renderersMap.get(Objects.requireNonNull(cell));
        }
    
        public void putEditor(Cell cell, TableCellEditor editor) {
            editorsMap.put(Objects.requireNonNull(cell), editor);
        }
    
        public TableCellEditor getEditor(Cell cell) {
            return editorsMap.get(Objects.requireNonNull(cell));
        }
    
        @Override
        public TableCellRenderer getCellRenderer(int row, int column) {
            TableCellRenderer result = renderersMap.get(new Cell(row, column));
            return result == null ? super.getCellRenderer(row, column) : result;
        }
    
        @Override
        public TableCellEditor getCellEditor(int row, int column) {
            return editorsMap.get(new Cell(row, column)); // when null - no editing
        }
    }
    
    // defined in CellBasedTableModel.java
    public class CellBasedTableModel extends DefaultTableModel {
        private Collection<Cell> editableCells = new HashSet<>();
    
        public CellBasedTableModel() {
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public boolean isCellEditable(int row, int column) {
            return editableCells.contains(new Cell(row, column));
        }
    
        public void addEditableCell(Cell cell) {
            editableCells.add(cell);
        }
    
        public void removeEditableCell(Cell cell) {
            editableCells.remove(cell);
        }
    }
    
    // defined in Cell.java
    public class Cell {
        private final int row, col;
    
        public Cell(int row, int col) {
            this.row = row;
            this.col = col;
        }
    
        public int getRow() {
            return row;
        }
    
        public int getCol() {
            return col;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Cell) {
                Cell another = (Cell) obj;
                return another.col == col && another.row == row;
            }
            return false;
        }
    
        @Override
        public int hashCode() {
            return Arrays.hashCode(new int[] {row, col});
        }
    }
    

    【讨论】:

    • 嗯...谢谢你的帮助,可能我的表达方式不正确,我的要求,例如当我点击cell(1,1)时,JTable会在这个cell上弹出一个JcomboBox组件,并且当我点击单元格(n,1)时,jtable不会弹出任何内容,n指的是其他行号
    • @huyangqing 很简单。您可以在 JTable 中覆盖方法 getCellEditor(int row, int column)。我已经为您修改了第二个示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    相关资源
    最近更新 更多