javaswingjtablejcombobox

CellEditor that puts one object's field/object to the JTable model, but you select it through dropdown based on another String property of that object


How to write own CellEditor that accepts list of non-String objects, shows the JComboBox dropdown with one filed of the Object, but when selected it adds another field of the Object to the JTable model.

To write a custom cell editor that accepts a list of non-String objects and shows a JComboBox dropdown with one field of the object, but adds another field of the object to the JTable model when selected, we create a class that extends AbstractCellEditor and implements TableCellEditor. Here's an example:

public class MyObjectCellEditor extends AbstractCellEditor implements TableCellEditor {
    private JComboBox<Object> comboBox;
    private Object selectedObject;

    public MyObjectCellEditor(List<Object> objectList) {
        comboBox = new JComboBox<>(objectList.toArray());
        comboBox.setRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                setText(((MyObject)value).getFieldToShow());
                return this;
            }
        });
        comboBox.addActionListener(e -> {
            selectedObject = comboBox.getSelectedItem();
            fireEditingStopped();
        });
    }

    @Override
    public Object getCellEditorValue() {
        return selectedObject.getFieldToAdd();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        selectedObject = (MyObject)value;
        comboBox.setSelectedItem(selectedObject);
        return comboBox;
    }
}

In this example, the custom cell editor takes a list of non-String objects in the constructor and creates a JComboBox with a custom renderer that displays one field of the object. The actionPerformed method of the JComboBox is overridden to set the selectedObject field and fire an editingStopped event. The getCellEditorValue method returns the fieldToAdd of the selectedObject. The getTableCellEditorComponent method sets the selectedObject to the value of the cell being edited and sets the selected item of the JComboBox to the selectedObject.

To use this custom cell editor, we create a JTable and set the cell editor for a specific column:

JTable table = new JTable();
List<MyObject> objectList = new ArrayList<>();
// add objects to objectList
table.getColumnModel().getColumn(0).setCellEditor(new MyObjectCellEditor(objectList));

But how to make the list of Objects for JComboBox to be dynamically updated by the external events?


Solution

  • JComboBox has own model too!

    This will use the MyObjectCellEditor for the first column of the JTable with the list of objects passed to the constructor. When an item is selected from the dropdown, the fieldToAdd of the selected object will be added to the JTable model.

    public void updateObjectList(List<Object> objectList) {
        comboBox.setModel(new DefaultComboBoxModel<>(objectList.toArray()));
    }
    

    This method takes a new list of objects and sets it as the model for the JComboBox. To use this method, you can call it whenever the list of objects needs to be updated. For example:

    MyObjectCellEditor cellEditor = new MyObjectCellEditor(objectList);
    table.getColumnModel().getColumn(0).setCellEditor(cellEditor);
    
    // update the objectList and the cell editor
    objectList.add(new MyObject("new object", "new value"));
    cellEditor.updateObjectList(objectList);
    

    In this example, a new MyObject is added to the objectList and the updateObjectList method is called on the cell editor to update the JComboBox with the new list of objects. When the JComboBox is opened, it will show the new object in the dropdown list.