如何使用自定义JTable单元格编辑器和单元格渲染器

我创建了一个带有自定义表格渲染和自定义单元格编辑器的JTable,它可以在图像中显示结果

在此处输入图像描述

我使用扩展JPanel的单独类创建了第一个表格单元格中显示的面板。 并将表值添加为,

tbl.setCellEditor(new customCell()); tbl.getColumnModel().getColumn(0).setCellRenderer(new customCell()); DefaultTableModel dtm = (DefaultTableModel) tbl.getModel(); Vector v = new Vector(); v.add(new Panel()); v.add("Test"); dtm.addRow(v); v.clear(); v.add(new Panel()); v.add("Test 2"); dtm.addRow(v); 

这是我的表自定义类来创建这个表,

 class customCell extends DefaultTableModel implements TableCellRenderer, TableCellEditor { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Panel p = new Panel(); table.setRowHeight(row, p.getHeight()); return p; } public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { return new Panel(); } public Object getCellEditorValue() { return ""; } public boolean isCellEditable(EventObject anEvent) { throw new UnsupportedOperationException("Not supported yet."); } public boolean shouldSelectCell(EventObject anEvent) { return true; } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } public boolean stopCellEditing() { return true; } public void cancelCellEditing() { throw new UnsupportedOperationException("Not supported yet."); } public void addCellEditorListener(CellEditorListener l) { throw new UnsupportedOperationException("Not supported yet."); } public void removeCellEditorListener(CellEditorListener l) { throw new UnsupportedOperationException("Not supported yet."); } } 

我的问题被认为面板显示为我预期我无法输入文本字段或更改复选框或单击按钮。 请告诉我如何解决这个问题。

必须为已经可见的JPanel添加适当的LayoutManagerEditable/non_Editable属性

让我们享受吧

 import java.awt.*; import java.awt.event.*; import java.util.EventObject; import javax.swing.*; import javax.swing.table.*; public class PanelInTable { private JFrame frame; private JTable compTable = null; private PanelTableModel compModel = null; private JButton addButton = null; public static void main(String args[]) { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception fail) { } SwingUtilities.invokeLater(() -> { new PanelInTable().makeUI(); }); } public void makeUI() { compTable = CreateCompTable(); JScrollPane CompTableScrollpane = new JScrollPane(compTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JPanel bottomPanel = CreateBottomPanel(); frame = new JFrame("Comp Table Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(CompTableScrollpane, BorderLayout.CENTER); frame.add(bottomPanel, BorderLayout.SOUTH); frame.setPreferredSize(new Dimension(800, 400)); frame.setLocation(150, 150); frame.pack(); frame.setVisible(true); } public JTable CreateCompTable() { compModel = new PanelTableModel(); compModel.addRow(); JTable table = new JTable(compModel); table.setRowHeight(new CompCellPanel().getPreferredSize().height); table.setTableHeader(null); PanelCellEditorRenderer PanelCellEditorRenderer = new PanelCellEditorRenderer(); table.setDefaultRenderer(Object.class, PanelCellEditorRenderer); table.setDefaultEditor(Object.class, PanelCellEditorRenderer); return table; } public JPanel CreateBottomPanel() { addButton = new JButton("Add Comp"); addButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { Object source = ae.getSource(); if (source == addButton) { compModel.addRow(); } } }); JPanel panel = new JPanel(new GridBagLayout()); panel.add(addButton); return panel; } } class PanelCellEditorRenderer extends AbstractCellEditor implements TableCellRenderer, TableCellEditor { private static final long serialVersionUID = 1L; private CompCellPanel renderer = new CompCellPanel(); private CompCellPanel editor = new CompCellPanel(); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { renderer.setComp((Comp) value); return renderer; } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { editor.setComp((Comp) value); return editor; } @Override public Object getCellEditorValue() { return editor.getComp(); } @Override public boolean isCellEditable(EventObject anEvent) { return true; } @Override public boolean shouldSelectCell(EventObject anEvent) { return false; } } class PanelTableModel extends DefaultTableModel { private static final long serialVersionUID = 1L; @Override public int getColumnCount() { return 1; } public void addRow() { super.addRow(new Object[]{new Comp(0, 0, "", "")}); } } class Comp { public int type; public int relation; public String lower; public String upper; public Comp(int type, int relation, String lower, String upper) { this.type = type; this.relation = relation; this.lower = lower; this.upper = upper; } } class CompCellPanel extends JPanel { private static final long serialVersionUID = 1L; private JLabel labelWith = new JLabel("With "); private JComboBox typeCombo = new JComboBox(new Object[] {"height", "length", "volume"}); private JComboBox relationCombo = new JComboBox(new Object[] {"above", "below", "between"}); private JTextField lowerField = new JTextField(); private JLabel labelAnd = new JLabel(" and "); private JTextField upperField = new JTextField(); private JButton removeButton = new JButton("remove"); public CompCellPanel() { setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); relationCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { enableUpper(relationCombo.getSelectedIndex() == 2); } }); enableUpper(false); removeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JTable table = (JTable) SwingUtilities.getAncestorOfClass( JTable.class, (Component) e.getSource()); int row = table.getEditingRow(); table.getCellEditor().stopCellEditing(); ((DefaultTableModel) table.getModel()).removeRow(row); } }); add(labelWith); add(typeCombo); add(relationCombo); add(lowerField); add(labelAnd); add(upperField); add(Box.createHorizontalStrut(100)); add(removeButton); } private void enableUpper(boolean enable) { labelAnd.setEnabled(enable); upperField.setEnabled(enable); } public void setComp(Comp Comp) { typeCombo.setSelectedIndex(Comp.type); relationCombo.setSelectedIndex(Comp.relation); lowerField.setText(Comp.lower); upperField.setText(Comp.upper); enableUpper(Comp.relation == 2); } public Comp getComp() { return new Comp(typeCombo.getSelectedIndex(), relationCombo.getSelectedIndex(), lowerField.getText(), upperField.getText()); } } 

我强烈建议重用默认表格渲染器和编辑器中提供的function,因为您的代码有很多问题

  1. 请拆分编辑器,渲染器和表格模型。 将它们全部放在同一个类中只是很奇怪
  2. 对于渲染器,不要每次都创建Component新实例。 相反,重用相同的组件,只需在getTableCellRendererComponent方法中修改该Component
  3. 编辑器Component
  4. 扩展默认编辑器,而不是使用UnsupportedOperationException实现方法,或者只返回空String

为了支持我的观点,请参阅JTable教程中的编辑部分 :

如果要指定除文本字段,复选框或combobox之外的编辑器,该怎么办? 由于DefaultCellEditor不支持其他类型的组件,因此您必须多做一些工作。 您需要创建一个实现TableCellEditor接口的类。 AbstractCellEditor类是一个很好用的超类。 它实现了TableCellEditor的超级接口CellEditor,为您节省了实现单元编辑器所需的事件触发代码的麻烦。

您的单元编辑器类需要至少定义两个方法 – getCellEditorValue和getTableCellEditorComponent。 CellEditor所需的getCellEditorValue方法返回单元格的当前值。 TableCellEditor所需的getTableCellEditorComponent方法应配置并返回要用作编辑器的组件。

正如在那里清楚解释的那样,你必须实现事件激发码:

为您节省了实现单元格编辑器所需的事件触发代码的麻烦。

你明显忽略了。 因此,我建议从AbstractCellEditor开始,而不是从头开始实现接口