JTable 中的自定义组合框不会设置选定的选项

Custom Combo box in JTable wont set the selected option

我创建了一个自定义组合框,用于显示订单状态可能发生的变化。我是在这个 post 的帮助下完成的,使用 MadProgrammer 的代码作为基线:

Changing Dropdown content in a JTable Column in Swing

部分有效。 即使在单击组合框后激活并为用户显示正确的状态选项,它仍然存在以下问题。

用户选择选项后,组合框不会在 table 中设置所选值。但是,如果用户更改另一个订单的组合框,则更改会发生。如果您单击选定行的非组合框单元格的其他部分,它也有效。

我怀疑这是因为单元格只有在单击时才会变成组合框,所以它的行为不像组合框。但是我对如何修复它有点迷茫。

非常感谢任何帮助。

以下是我的代码的相关部分:

编辑:按照 Andrew Thompson 的建议,我用可重现的示例替换了代码。我将致力于 MadProgrammer 的建议解决方案并稍后更新。

package test;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

public class TestCellEditor {

    public static void main(String[] args) {
        new TestCellEditor();
    }

    public TestCellEditor() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {                

                List<String> values = new ArrayList<>(5);
                values.add("B");
                values.add("A");
                values.add("O");
                values.add("G");
                values.add("P");

                ComboBoxTableCellEditor editor = new ComboBoxTableCellEditor(values);
                DefaultTableModel model = new  DefaultTableModel(new Object[]{"Status"}, 5);
                JTable table = new JTable(model);
                table.getColumnModel().getColumn(0).setCellEditor(editor);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ComboBoxTableCellEditor extends AbstractCellEditor implements TableCellEditor {

        private JComboBox editor;
        private List<String> masterValues;

        public ComboBoxTableCellEditor(List<String> masterValues) {
            this.editor = new JComboBox();
            this.masterValues = masterValues;
        }

        @Override
        public Object getCellEditorValue() {
            return editor.getSelectedItem();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {

            DefaultComboBoxModel model = new DefaultComboBoxModel(masterValues.toArray(new String[masterValues.size()]));
            for (int index = 0; index < table.getRowCount(); index++) {

            }

            editor.setModel(model);
            editor.setSelectedItem(value);

            return editor;

        }
    }

}

根据@camickr 的建议,我设法实现了一个更简单的解决方案。

我把它放在填充 table 的方法上:

table.getColumnModel().getColumn(5).setCellEditor(getCellEditor(status));
public List<TableCellEditor> TableComboBoxByRow(){
        // Create the editors to be used for each row
        List<TableCellEditor> editors = new ArrayList<TableCellEditor>(3);
        String[] items1 = { "I", "C", "F" };
        JComboBox comboBox1 = new JComboBox( items1 );
        DefaultCellEditor dce1 = new DefaultCellEditor( comboBox1 );
        editors.add( dce1 );
        
        String[] items2 = { "E" };
        JComboBox comboBox2 = new JComboBox( items2 );
        DefaultCellEditor dce2 = new DefaultCellEditor( comboBox2 );
        editors.add( dce2 );

        String[] items3 = { "ET" };
        JComboBox comboBox3 = new JComboBox( items3 );
        DefaultCellEditor dce3 = new DefaultCellEditor( comboBox3 );
        editors.add( dce3 );
        
        String[] items4 = { "F" };
        JComboBox comboBox4 = new JComboBox( items4 );
        DefaultCellEditor dce4 = new DefaultCellEditor( comboBox4 );
        editors.add( dce4 );
        return editors;
 }
public TableCellEditor getCellEditor(String status)
            {
                
                if(estado.equals("I") || estado.equals("C")){
                return TableComboBoxByRow().get(0);
                }
                else if(estado.equals("E"))
                {
                return TableComboBoxByRow().get(1);}
                else if(estado.equals("ET"))
                {
                return TableComboBoxByRow().get(2);   
                }else{   
                return TableComboBoxByRow().get(3);                                     
                }
                
            }

非常感谢!

此方法只会重写 DefaultCellEditor 的 getTableCellEditorComponent(...) 方法,以根据正在编辑的当前行中的值重置组合框的模型。

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.table.*;

public class StateCellEditor extends DefaultCellEditor
{
    private int lookupColumn;
    private HashMap<Object, DefaultComboBoxModel<?>> map;

    public StateCellEditor(JComboBox<?> comboBox, int lookColumn, HashMap<Object, DefaultComboBoxModel<?>> map)
    {
        super(comboBox);
        this.lookupColumn = lookupColumn;
        this.map = map;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
    {
        Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);

        JComboBox<?> comboBox = (JComboBox<?>)c;

        Object lookup = table.getModel().getValueAt(row, lookupColumn);
        DefaultComboBoxModel model = map.get( lookup );
        comboBox.setModel( model );

        return comboBox;
    }

    private static void createAndShowUI()
    {
        HashMap<Object, DefaultComboBoxModel<?>> map = new HashMap<>();
        map.put("Color", new DefaultComboBoxModel<Object>( new String[]{ "Red", "Blue", "Green" } ));
        map.put("Shape", new DefaultComboBoxModel<Object>( new String[]{ "Circle", "Square", "Triangle" } ));
        map.put("Fruit", new DefaultComboBoxModel<Object>( new String[]{ "Apple", "Orange", "Banana" } ));

        JPanel panel = new JPanel( new BorderLayout() );
        panel.setLayout( new BorderLayout() );

        //  Create the table with default data

        Object[][] data =
        {
            {"Color", "Red"},
            {"Shape", "Square"},
            {"Fruit", "Banana"}
        };
        String[] columnNames = {"Type","Value"};

        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        JTable table = new JTable(model);
        DefaultCellEditor dce = new StateCellEditor(new JComboBox<Object>(), 0, map);
        table.getColumnModel().getColumn(1).setCellEditor(dce);

        JScrollPane scrollPane = new JScrollPane( table );
        panel.add( scrollPane );

        JFrame frame = new JFrame("Table Combo Box by Row");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel, BorderLayout.CENTER);
        frame.setSize(200, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}