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();
}
});
}
}
我创建了一个自定义组合框,用于显示订单状态可能发生的变化。我是在这个 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();
}
});
}
}