
I recently was asked to add a column to an existing JTable to display a list of data using a JComboBox. Each row has its own set of data to display. All examples of JComboBox usage within a JTable I could find was for a set of data to be displayed for every row.
In order to see the combobox when both clicking it (editing) and viewing I had to create both a TableCellEditor and a TableCellRenderer.
public class ComboEditor
extends AbstractCellEditor
implements TableCellEditor {
private JComboBox cb = new JComboBox();
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row,
int column) {
if (value instanceof String[]) {
DefaultComboBoxModel m = new DefaultComboBoxModel((String[]) value);
cb.setModel(m);
return cb;
} else {
return null;
}
}
public Object getCellEditorValue() {
return cb.getSelectedItem();
}
}
public class ComboCellRenderer extends DefaultTableCellRenderer {
/** Creates a new instance of MusicCellRenderer */
public ComboCellRenderer() {
setOpaque(false);
setHorizontalAlignment(SwingConstants.LEFT);
}
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (value instanceof String[]) {
//don't actually create a new one every time if you don't need to
final JComboBox cb = new JComboBox(((String[]) value));
cb.setEditable(false);
cb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cb.setSelectedIndex(0);
}
});
setColors(cb, row, isSelected);
cb.setOpaque(true);
cb.setFont(table.getFont());
return cb;
} else {
try {
setText(value.toString());
} catch (Exception e) {
setText(null);
}
}
setFont(table.getFont());
setOpaque(true);
setColors(this, row, isSelected);
return this;
}
I was able to see the comboboxes in the table couldn’t interact with them to get them to drop down. In order to do this I needed to make that column editable by overriding the isCellEditable method.
@Override
public boolean isCellEditable(int row, int col) {
if (col == COLUMN_COMBO) {
return true;
}
return false;
}
I hate posts that do not include runnable source so here you go.
I am certainly going to tweak this code before I’m done for both memory usage and performance.