[英]JComboBox as Jtable CellEditor with Overriden stopCellEditing modifies wrong table cell
I have a custom JTable with a custom TableModel using a JComboBox as a cell editor. 我有一个自定义的JTable与自定义TableModel使用JComboBox作为单元格编辑器。 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.
ComboBox还有一个自定义的ComboBoxModel.ComboBox模型包含多个字段,这些字段将用于更新JTable后面的数据,然后更新数据库。
The following is a simple example to show the problem I am encountering. 以下是一个简单的示例,以显示我遇到的问题。 Steps to reproduce:
重现步骤:
The second cell will get the value from the first one. 第二个单元格将从第一个单元格中获取值。
Why is this happening? 为什么会这样? Why does the ComboBox model change before stopCellEditing exists?
为什么在stopCellEditing存在之前ComboBox模型会发生变化?
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);
}
}
Ok, I've done some changes and I think I got something working. 好的,我做了一些改变,我觉得我有一些工作。 If it is not the best practice and you got a better implementation, please post an answer.
如果这不是最佳实践,并且您有更好的实施,请发布答案。
Edit: Do not follow the example below! 编辑:不要按照下面的例子! Following kleopatra's comments it is a wrong implementation.
根据kleopatra的评论,这是一个错误的实现。 I'm leaving it here so you know how not to do it.
我离开这里,所以你知道怎么不去做。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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)) {
comboBox.actionPerformed(new ActionEvent(this, selectedIndex, "blabla"));
} 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();
}
});
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// the selected item exists as an Option inside the ComboBox
if (e.getActionCommand().equals("blabla")) {
DefaultComboBoxModel comboModel = (DefaultComboBoxModel) comboBox.getModel();
String selectedItem = (String) comboModel.getSelectedItem();
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
tableModel.setValueAt(selectedItem, selectedRow, selectedColumn);
}
}
});
// pack and show frame
frame.pack();
frame.setVisible(true);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.