自定义的JTable中的组合框无法设置所选选项。

huangapple go评论81阅读模式
英文:

Custom Combo box in JTable wont set the selected option

问题

I've created a custom combo box that displays possible changes in state for orders. I did it with the help of this post, using MadProgrammer's code as a baseline:

https://stackoverflow.com/questions/27009657/changing-dropdown-content-in-a-jtable-column-in-swing

It worked, partially.
Even though after clicking the combo box is activated and it shows the proper state options for the user, it has the following problem.

After the user selects the option, the combo box doesn't set the selected value in the table. However, if the user changes the combo box of another order, the change does take place. It also works if you click another part of the selected row that isn't the combo box cell.

I suspect that this is because the cell only changes to be a combo box when it's clicked, so it doesn't behave like a combo box does. Yet I'm a bit lost in how to fix it.

Any help is greatly appreciated.

Here are the relevant parts of my code:

EDIT: Following Andrew Thompson's advice, I replaced the code with a reproducible example. I'll be working on MadProgrammer's suggested solution and update it later.

英文:

I've created a custom combo box that displays possible changes in state for orders. I did it with the help of this post, using MadProgrammer's code as base line:

https://stackoverflow.com/questions/27009657/changing-dropdown-content-in-a-jtable-column-in-swing

It worked, partially.
Even though after clicking the combo box is activated and it shows the proper state options for the user, it has the following problem.

After the user selects the option, the combo box doesn't set the selected value in the table. However if the user changes the combo box of another order, the change does take place. It also works if you click other part of the selected row that isn't the combo box cell.

I suspect that this is because the cell only changes to be a combo box when is clicked, so it doesn't behave like a combo box does. Yet I'm a bit lost in how to fix it.

Any help is greatly appreciated.

Here are the relevant parts of my code:

EDIT: Following Andrew Thompson's advice, i replaced the code with a reproducible example. I'll be working on MadProgrammer's suggested solution and update it later.

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;

        }
    }

}

答案1

得分: 0

以下是已经翻译好的内容:

Following the suggestion of @camickr i managed to implement an easier solution.

I put this on the method that populates the 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(status.equals("I") || status.equals("C")){
    return TableComboBoxByRow().get(0);
    }
    else if(status.equals("E"))
    {
    return TableComboBoxByRow().get(1);}
    else if(status.equals("ET"))
    {
    return TableComboBoxByRow().get(2);   
    }else{   
    return TableComboBoxByRow().get(3);                                     
    }
    
}

Thank you so much!

英文:

Following the suggestion of @camickr i managed to implement an easier solution.

I put this on the method that populates the table:

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

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

Thank you so much!

答案2

得分: 0

这种方法只会覆盖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 = lookColumn;
        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();
            }
        });
    }
}
英文:

This approach will only override the getTableCellEditorComponent(...) method of the DefaultCellEditor to reset the model of the combo box based on a value in the current row that is being edited.

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&lt;Object, DefaultComboBoxModel&lt;?&gt;&gt; map;
public StateCellEditor(JComboBox&lt;?&gt; comboBox, int lookColumn, HashMap&lt;Object, DefaultComboBoxModel&lt;?&gt;&gt; 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&lt;?&gt; comboBox = (JComboBox&lt;?&gt;)c;
Object lookup = table.getModel().getValueAt(row, lookupColumn);
DefaultComboBoxModel model = map.get( lookup );
comboBox.setModel( model );
return comboBox;
}
private static void createAndShowUI()
{
HashMap&lt;Object, DefaultComboBoxModel&lt;?&gt;&gt; map = new HashMap&lt;&gt;();
map.put(&quot;Color&quot;, new DefaultComboBoxModel&lt;Object&gt;( new String[]{ &quot;Red&quot;, &quot;Blue&quot;, &quot;Green&quot; } ));
map.put(&quot;Shape&quot;, new DefaultComboBoxModel&lt;Object&gt;( new String[]{ &quot;Circle&quot;, &quot;Square&quot;, &quot;Triangle&quot; } ));
map.put(&quot;Fruit&quot;, new DefaultComboBoxModel&lt;Object&gt;( new String[]{ &quot;Apple&quot;, &quot;Orange&quot;, &quot;Banana&quot; } ));
JPanel panel = new JPanel( new BorderLayout() );
panel.setLayout( new BorderLayout() );
//  Create the table with default data
Object[][] data =
{
{&quot;Color&quot;, &quot;Red&quot;},
{&quot;Shape&quot;, &quot;Square&quot;},
{&quot;Fruit&quot;, &quot;Banana&quot;}
};
String[] columnNames = {&quot;Type&quot;,&quot;Value&quot;};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model);
DefaultCellEditor dce = new StateCellEditor(new JComboBox&lt;Object&gt;(), 0, map);
table.getColumnModel().getColumn(1).setCellEditor(dce);
JScrollPane scrollPane = new JScrollPane( table );
panel.add( scrollPane );
JFrame frame = new JFrame(&quot;Table Combo Box by Row&quot;);
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();
}
});
}
}

huangapple
  • 本文由 发表于 2020年8月14日 12:24:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/63406524.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定