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

问题描述

我创建了一个自定义组合框,用于显示订单状态的可能变化。我在这文章的帮助下做到了这一点,使用MadProgrammer的代码作为基线:

Changing Dropdown content in a JTable Column in Swing

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

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

我怀疑这是因为单击时该单元格仅更改为组合框,因此它的行为不像组合框那样。但是我对如何解决它有些迷茫。

非常感谢您的帮助。

这是我代码的相关部分:

编辑:按照安德鲁·汤普森(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.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>(),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();
            }
        });
    }
}