Cómo usar el editor de células JTable personalizado y el procesador de células

Creé una JTable con un renderizado de tabla personalizado y un editor de celda personalizado que da el resultado en la imagen

enter image description here

Creé el panel que se muestra en las primeras celdas de la tabla usando una clase separada que extendió JPanel. y agregue valores de tabla como,

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

Y esta es mi clase personalizada de mesa para crear esta tabla,

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

Mi problema es que el panel se muestra como esperaba. No puedo escribir en el campo de texto o cambiar la checkbox o hacer clic en el botón. por favor dime como resolver esto.

tiene que agregar LayoutManager , Editable/non_Editable adecuadas para JPanel ya visible

deja disfrutar

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

Recomiendo encarecidamente reutilizar la funcionalidad disponible en los renderizadores y editores de tablas predeterminados, ya que hay muchas cosas mal con su código

  1. Por favor divida su editor, procesador y modelo de tabla. Tenerlos a todos en la misma clase es simplemente raro
  2. Para su procesador, no cree nuevas instancias de un Component cada vez. En su lugar, reutilice el mismo componente y simplemente modifique ese Component en el método getTableCellRendererComponent
  3. Lo mismo aplica para el editor Component
  4. Extienda un editor predeterminado en lugar de implementar los métodos con UnsupportedOperationException o simplemente devolviendo String vacías.

Para hacer una copia de seguridad de mi cuarto punto, una pequeña cita de la parte de Editores en el tutorial de JTable :

¿Qué sucede si desea especificar un editor que no sea un campo de texto, checkbox o cuadro combinado? Como DefaultCellEditor no admite otros tipos de componentes, debe hacer un poco más de trabajo. Necesita crear una clase que implemente la interfaz TableCellEditor. La clase AbstractCellEditor es una buena superclase para usar. Implementa la superinterfaz de TableCellEditor, CellEditor, lo que le ahorra la molestia de implementar el código de activación de eventos necesario para los editores de células.

Su clase de editor de célula necesita definir al menos dos métodos: getCellEditorValue y getTableCellEditorComponent. El método getCellEditorValue, requerido por CellEditor, devuelve el valor actual de la celda. El método getTableCellEditorComponent, requerido por TableCellEditor, debe configurar y devolver el componente que desea usar como editor.

Como se explica claramente allí, debe implementar el código de activación del evento:

ahorrándole la molestia de implementar el código de activación de eventos necesario para los editores de células.

que claramente descuidó. Por lo tanto, mi consejo es comenzar desde AbstractCellEditor lugar de implementar la interfaz desde cero.