JComboBox作为Jtable CellEditor与Overriden stopCellEditing修改错误的表格单元格 [英] JComboBox as Jtable CellEditor with Overriden stopCellEditing modifies wrong table cell
问题描述
我有一个自定义JTable与自定义TableModel使用JComboBox作为单元格编辑器。 ComboBox还有一个自定义的ComboBoxModel
ComboBox模型包含多个字段,用于更新JTable后面的数据,然后更新数据库。
I have a custom JTable with a custom TableModel using a JComboBox as a cell editor. The ComboBox also has a custom ComboBoxModel The ComboBox model holds multiple fields that will be used to update the data behind the JTable and afterwards update a database.
下面是一个简单的例子来展示我遇到的问题。重现步骤:
The following is a simple example to show the problem I am encountering. Steps to reproduce:
- 点击某个单元格
- 从ComboBox下拉列表中选择一个值
- 点击其他单元格
- 点击第一个选择的单元格
- Click on an cell
- Select a value from the ComboBox drop-down list
- Click on a different cell
- Click back on the first selected cell
第二个单元格将从第一个单元格获取值。
The second cell will get the value from the first one.
为什么会发生这种情况?为什么在stopCellEditing存在之前ComboBox模型改变了?
Why is this happening? Why does the ComboBox model change before stopCellEditing exists?
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class TestComboCellEditor {
public static void main(String[] args) {
TestComboCellEditor test = new TestComboCellEditor();
test.go();
}
public void go() {
//create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create and add a tabbed pane to the frame
JTabbedPane tabbedPane = new JTabbedPane();
frame.getContentPane().add(tabbedPane);
//create a table and add it to a scroll pane in a new tab
final JTable table = new JTable(new DefaultTableModel(new Object[]{"A", "B"}, 5));
JScrollPane scrollPane = new JScrollPane(table);
tabbedPane.addTab("test", scrollPane);
// create a simple JComboBox and set is as table cell editor on column A
Object[] comboElements = {"aaaaa1", "aaaaaa2", "b"};
final JComboBox comboBox = new JComboBox(comboElements);
comboBox.setEditable(true);
table.getColumn("A").setCellEditor(new DefaultCellEditor(comboBox) {
@Override
public boolean stopCellEditing() {
if (comboBox.isEditable()) {
DefaultComboBoxModel comboModel = (DefaultComboBoxModel) comboBox.getModel();
String selectedItem = (String) comboModel.getSelectedItem();
int selectedIndex = comboModel.getIndexOf(selectedItem);
if (!(selectedIndex == -1)) {
// the selected item exists as an Option inside the ComboBox
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
tableModel.setValueAt(selectedItem, selectedRow, selectedColumn);
} else if (selectedItem != null) {
// missing code - adding new info to a custom JComboBox model and to alter info inside a custom table model
}
}
return super.stopCellEditing();
}
});
// pack and show frame
frame.pack();
frame.setVisible(true);
}
}
推荐答案
这里是一种保留编辑器中所有代码的方法:
Here is an approach that keeps all the code in the editor:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class TestComboCellEditor {
public static void main(String[] args) {
TestComboCellEditor test = new TestComboCellEditor();
test.go();
}
public void go() {
//create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create and add a tabbed pane to the frame
JTabbedPane tabbedPane = new JTabbedPane();
frame.getContentPane().add(tabbedPane);
//create a table and add it to a scroll pane in a new tab
final JTable table = new JTable(new DefaultTableModel(new Object[]{"A", "B"}, 5));
JScrollPane scrollPane = new JScrollPane(table);
tabbedPane.addTab("test", scrollPane);
// create a simple JComboBox and set is as table cell editor on column A
Object[] comboElements = {"aaaaa1", "aaaaaa2", "b"};
final JComboBox comboBox = new JComboBox(comboElements);
comboBox.setEditable(true);
table.getColumn("A").setCellEditor(new DefaultCellEditor(comboBox)
{
private Object originalValue;
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
originalValue = value;
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
@Override
public boolean stopCellEditing()
{
JComboBox comboBox = (JComboBox)getComponent();
DefaultComboBoxModel comboModel = (DefaultComboBoxModel) comboBox.getModel();
Object editingValue = getCellEditorValue();
// Needed because your TableModel is empty
if (editingValue == null)
return super.stopCellEditing();
int selectedIndex = comboModel.getIndexOf(editingValue);
// Selecting item from model
if (! (selectedIndex == -1))
return super.stopCellEditing();
// Confirm addition of new value
int result = JOptionPane.showConfirmDialog(
comboBox.getParent(),
"Add (" + editingValue + ") to table?",
"Update Model",
JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION)
{
comboBox.addItem(editingValue);
return super.stopCellEditing();
}
else
{
comboBox.removeItem(editingValue);
comboBox.setSelectedItem(originalValue);
return false;
}
}
});
// pack and show frame
frame.pack();
frame.setVisible(true);
}
}
这篇关于JComboBox作为Jtable CellEditor与Overriden stopCellEditing修改错误的表格单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!