简体   繁体   中英

JComboBox within JTable not saving selection

I have a JTable which contains a Name and Choice column. I would like for the Choice column to contain a JComboBox Component that has the same selection for every row, although allow for independent selection for every unique row.

Currently, interacting with the JComboBox within the column allows for the drop-down to appear for a selection to be made; although, no selection is saved.

在此处输入图像描述

Instead, the selection made migrates to any JComboBox that I click on. Eg, I click on the first row's JComboBox and select "Choice B", but all choices still appear as "Choice A". It isn't until I click on another row's JComboBox that the drop-down appears with the "Choice B" selection highlighted.

The code used for this table is as follows:

final String[] choices = new String[]{"Choice A", "Choice B", "Choice C"};
final Collection<String> mockData = Arrays.asList("First", "Second", "Third", "Fourth", "Fifth", "Sixth");
table.setModel(new MasterTableModel(mockData.stream().map(s -> {
    return new Object[]{s, new JComboBox<>(choices)};
}).collect(Collectors.toSet())));
table.setDefaultEditor(JComboBox.class, new DefaultCellEditor(new JComboBox<>(choices)));
table.setDefaultRenderer(JComboBox.class, new MasterTableComboRenderer(table.getDefaultRenderer(JComboBox.class)));

I have three choices, which are used to initalize JComboBox es that populate the Choice column. I set the DefaultRenderer to my custom MasterTableComboRenderer object which implements the TableCellRenderer interface so as to have the JComboBox show up as a Component rather than to print the address of the object. It only requires the overriding of a single method:

class MasterTableComboRenderer ...
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
    return value instanceof Component ? (Component) value : renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}

Finally, MasterTableModel is a simple extension of AbstractTableModel , which defines the column headers [Name, Choice] and holds an Object[][] reperesenting the JTable 's data. I've overriden isCellEditable and getColumnClass as follows:

class MasterTableModel...
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
    return getColumnName(columnIndex).equals("Choice");
}

@Override
public Class<?> getColumnClass(final int columnIndex) {
    return getValueAt(0, columnIndex).getClass();
}

Is there something I've been missing to achieve the functionality of the JComboBox saving its choices and not having the selection highlight migrate to other boxes?

A JComboBox should NOT be stored in the TableModel . The String value is stored in the model.

Read the section from the Swing tutorial on Using a Combo Box as a Renderer for a working example.

If you want the renderer to look like a combo box, then you need to use a combo box as a renderer. Something like:

class ComboBoxRenderer extends JComboBox implements TableCellRenderer
{
    public ComboBoxRenderer()
    {
        setBorder(null);
    }

    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        removeAllItems();
        addItem( value );

        return this;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM