Come utilizzare l’editor di celle e il rendering di celle JTable personalizzati

Ho creato un JTable con un rendering di tabelle personalizzate e un editor di celle personalizzato che dà il risultato nell’immagine

inserisci la descrizione dell'immagine qui

Ho creato il pannello mostrato nelle prime celle della tabella utilizzando una class separata che ha esteso JPanel. e aggiungi valori tabella come,

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

E questa è la mia class personalizzata da tavolo per creare questo tavolo,

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

Il mio problema si pensa che il pannello sia mostrato come mi aspettavo di non poter digitare nel campo di testo o modificare la casella di controllo o fare clic sul pulsante. per favore dimmi come risolvere questo

è necessario aggiungere il proprio LayoutManager , proprietà Editable/non_Editable già visibile

godiamoci

 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 actionPerformsd(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 actionPerformsd(ActionEvent e) { enableUpper(relationCombo.getSelectedIndex() == 2); } }); enableUpper(false); removeButton.addActionListener(new ActionListener() { @Override public void actionPerformsd(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()); } } 

Suggerisco caldamente di riutilizzare la funzionalità resa disponibile nei renderer e negli editor di tabelle predefiniti, poiché ci sono molte cose che non vanno nel tuo codice

  1. Si prega di dividere il tuo editor, il renderer e il modello di tabella. Averli tutti nella stessa class è solo strano
  2. Per il tuo renderer, non creare nuove istanze di un Component ogni volta. Invece, riutilizzare lo stesso componente e modificare semplicemente tale Component nel metodo getTableCellRendererComponent
  3. Lo stesso vale per l’editor Component
  4. Estendi un editor predefinito invece di implementare i metodi con UnsupportedOperationException o semplicemente restituendo String s vuota

Per eseguire il back-up del mio quarto punto, una piccola citazione dalla parte Editors nel tutorial di JTable :

Cosa fare se si desidera specificare un editor diverso da un campo di testo, una casella di controllo o una casella combinata? Siccome DefaultCellEditor non supporta altri tipi di componenti, devi fare un po ‘più di lavoro. È necessario creare una class che implementa l’interfaccia TableCellEditor. La class AbstractCellEditor è una buona superclass da utilizzare. Implementa la superinterfaccia di TableCellEditor, CellEditor, risparmiando la fatica di implementare il codice di triggerszione degli eventi necessario per gli editor di celle.

La class dell’editor di celle deve definire almeno due metodi: getCellEditorValue e getTableCellEditorComponent. Il metodo getCellEditorValue, richiesto da CellEditor, restituisce il valore corrente della cella. Il metodo getTableCellEditorComponent, richiesto da TableCellEditor, dovrebbe configurare e restituire il componente che si desidera utilizzare come editor.

Come spiegato chiaramente, devi implementare il codice di triggerszione dell’evento:

risparmiando la fatica di implementare il codice di triggerszione evento necessario per gli editor di celle.

che hai chiaramente trascurato. Pertanto il mio consiglio di partire da AbstractCellEditor invece di implementare l’interfaccia da zero