Search code examples
javaswingjtabletablecellrenderertablecelleditor

How to use custom JTable cell editor and cell renderer


I have created a JTable with a custom table render and custom cell editor which gives the result in the image

enter image description here

I created the panel shown in the first table cells using a separate class which extended JPanel. and add table values as,

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

And this is my table custom class to create this table,

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

My problem is thought the panel is shown as I expected I can't type into the text field or change check box or click the button. please tell me how to solve this.


Solution

  • have to add proper LayoutManager, Editable/non_Editable properties for already visible JPanel

    let enjoy

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