Reputation: 3578
I have created a JTable with a custom table render and custom cell editor which gives the result in the image
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.
Upvotes: 10
Views: 57999
Reputation: 109815
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());
}
}
Upvotes: 11
Reputation: 36601
I would strongly suggest to reuse the functionality made available in the default table renderers and editors, as there are many things wrong with your code
Component
each time. Instead, reuse the same component and just modify that Component
in the getTableCellRendererComponent
methodComponent
UnsupportedOperationException
s or by just returning empty String
sTo back-up my forth point, a little quote from the Editors part in the JTable
tutorial:
What if you want to specify an editor other than a text field, check box, or combo box? As DefaultCellEditor does not support other types of components, you must do a little more work. You need to create a class that implements the TableCellEditor interface. The AbstractCellEditor class is a good superclass to use. It implements TableCellEditor's superinterface, CellEditor, saving you the trouble of implementing the event firing code necessary for cell editors.
Your cell editor class needs to define at least two methods — getCellEditorValue and getTableCellEditorComponent. The getCellEditorValue method, required by CellEditor, returns the cell's current value. The getTableCellEditorComponent method, required by TableCellEditor, should configure and return the component that you want to use as the editor.
As clearly explained there you must implement the event firing code:
saving you the trouble of implementing the event firing code necessary for cell editors.
which you clearly neglected. Therefore my advise to start from AbstractCellEditor
instead of implementing the interface from scratch
Upvotes: 14