如何在JTable单元中单击JButton?

我有一个带有自定义单元格渲染器的JTable。 该单元格是一个包含JTextField和JButton的JPanel。 JTextField包含一个整数,当用户单击JButton时,应该增加整数。

问题是当我在JTable单元格中使用它时,无法单击JButton。 如何使其可点击?

在此处输入图像描述

这是我的测试代码:

public class ActiveTable extends JFrame { public ActiveTable() { RecordModel model = new RecordModel(); model.addRecord(new Record()); JTable table = new JTable(model); EditorAndRenderer editorAndRenderer = new EditorAndRenderer(); table.setDefaultRenderer(Object.class, editorAndRenderer); table.setDefaultEditor(Object.class, editorAndRenderer); table.setRowHeight(38); add(new JScrollPane(table)); setPreferredSize(new Dimension(600, 400)); pack(); setDefaultCloseOperation(EXIT_ON_CLOSE); setTitle("Active Table"); setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new ActiveTable(); } }); } class RecordModel extends AbstractTableModel { private final List records = new ArrayList(); @Override public int getColumnCount() { return 1; } @Override public int getRowCount() { return records.size(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { return records.get(rowIndex); } public void addRecord(Record r) { records.add(r); fireTableRowsInserted(records.size()-1, records.size()-1); } } class Record { private int count = 1; public int getCount() { return count; } public void increase() { count = count + 1; } } class CellPanel extends JPanel { private Record record; private final JTextField field = new JTextField(8); private final Action increaseAction = new AbstractAction("+") { public void actionPerformed(ActionEvent e) { record.increase(); field.setText(record.getCount()+""); JTable table = (JTable) SwingUtilities.getAncestorOfClass(JTable.class, (Component) e.getSource()); table.getCellEditor().stopCellEditing(); } }; private final JButton button = new JButton(increaseAction); public CellPanel() { add(field); add(button); } public void setRecord(Record r) { record = r; field.setText(record.getCount()+""); } public Record getRecord() { return record; } } class EditorAndRenderer extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { private final CellPanel renderer = new CellPanel(); private final CellPanel editor = new CellPanel(); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { renderer.setRecord((Record) value); return renderer; } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { editor.setRecord((Record) value); return editor; } @Override public Object getCellEditorValue() { return editor.getRecord(); } @Override public boolean isCellEditable(EventObject ev) { return true; } @Override public boolean shouldSelectCell(EventObject ev) { return false; } } } 

这是使用ButtonColumn的一种方法。

 public class TableTest extends JFrame { public TableTest() { this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTable table = new JTable(new TestModel()); table.getColumnModel().getColumn(1).setPreferredWidth(3); table.getColumnModel().getColumn(2).setPreferredWidth(3); this.add(new JScrollPane(table)); Action increase = new AbstractAction("+") { @Override public void actionPerformed(ActionEvent e) { JTable table = (JTable) e.getSource(); int row = Integer.valueOf(e.getActionCommand()); TestModel model = (TestModel) table.getModel(); model.increment(row, 0); } }; ButtonColumn inc = new ButtonColumn(table, increase, 1); Action decrease = new AbstractAction("-") { @Override public void actionPerformed(ActionEvent e) { JTable table = (JTable) e.getSource(); int row = Integer.valueOf(e.getActionCommand()); TestModel model = (TestModel) table.getModel(); model.decrement(row, 0); } }; ButtonColumn dec = new ButtonColumn(table, decrease, 2); pack(); } public static void main(String[] args) { new TableTest().setVisible(true); } } class TestModel extends AbstractTableModel { List records = new LinkedList(); private static class TestRecord { private int val = 0; } public void increment(int row, int col) { records.get(row).val++; fireTableCellUpdated(row, 0); } public void decrement(int row, int col) { records.get(row).val--; fireTableCellUpdated(row, 0); } public TestModel() { records.add(new TestRecord()); records.add(new TestRecord()); } @Override public Class getColumnClass(int col) { if (col == 0) { return Integer.class; } else { return ButtonColumn.class; } } @Override public boolean isCellEditable(int row, int col) { return true; } @Override public int getColumnCount() { return 3; } @Override public int getRowCount() { return records.size(); } @Override public Object getValueAt(int row, int col) { if (col == 0) { return records.get(row).val; } else if (col == 1) { return "+"; } else { return "-"; } } } 

我的最后一个例子是基于mKrobels提供的代码,回答如何在swing中实现动态GUI

他和我在问题中的例子的主要区别在于他使用DefaultTableModel而我使用AbstractTableModel 。 他的榜样确实有效,但不是我的。

我找到的解决方案是我必须在TableModel中实现isCellEditable() ,所以添加了这个方法,我的示例有效:

 @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } 

渲染器只是用于绘制单元格的显示器。 您需要一个允许您进行更改的编辑器组件。

看一眼:

http://download.oracle.com/javase/6/docs/api/javax/swing/table/TableCellEditor.html