提出的简单解决方案之一
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE)
这种方法只适用于字符串列。问题在于,如果我有一个浮点型的列正在编辑中,当我在相应的单元格中输入空字符串,然后单击窗口的任何其他控件 - Java会在JTable.java
的CellEditorRemover.propertyChange()
方法中抛出NullPointerException
。它调用getCellEditor()
来停止或取消编辑,但在这种情况下返回null
。如果输入的值不为空,或者我删除了terminateEditOnFocusLost
标志,一切都很好。可能,上述情况是一个bug。
我希望我能根据之前的一个帖子提供一种解决方案。这并不像我之前想象的那样简单,但我认为它可行。
我必须从默认单元格编辑器继承我的自己的单元格编辑器和我的自己的文本字段JTextField
。这个焦点监听器在编辑单元格失去焦点时运行良好,并且焦点被窗口的另一个控件获取时也很好。但是,在单元格选择更改的情况下,焦点监听器就会“失聪”。这就是为什么我还要在编辑开始之前记住先前有效的值,以便在输入的值无效时恢复它。
请参见下面的代码。经过测试,可用于Double
,Float
和Integer
,但我希望这也适用于Byte
和String
。
具有焦点监听器的文本框:
public class TextFieldCell extends JTextField {
public TextFieldCell(JTable cellTable) {
super();
final JTable table = cellTable;
this.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
CellEditor cellEditor = table.getCellEditor();
if (cellEditor != null)
if (cellEditor.getCellEditorValue() != null)
cellEditor.stopCellEditing();
else
cellEditor.cancelCellEditing();
}
});
}
}
默认的单元格编辑器类:
class TextFieldCellEditor extends DefaultCellEditor {
TextFieldCell textField;
Class<?> columnClass;
Object valueObject;
public TextFieldCellEditor(TextFieldCell tf, Class<?> cc) {
super(tf);
textField = tf;
columnClass = cc;
valueObject = null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
TextFieldCell tf = (TextFieldCell)super.getTableCellEditorComponent(table, value, isSelected, row, column);
if (value != null) {
tf.setText(value.toString());
}
valueObject = value;
return tf;
}
@Override
public Object getCellEditorValue() {
try {
if (columnClass.equals(Double.class))
return Double.parseDouble(textField.getText());
else if (columnClass.equals(Float.class))
return Float.parseFloat(textField.getText());
else if (columnClass.equals(Integer.class))
return Integer.parseInt(textField.getText());
else if (columnClass.equals(Byte.class))
return Byte.parseByte(textField.getText());
else if (columnClass.equals(String.class))
return textField.getText();
}
catch (NumberFormatException ex) {
}
if (valueObject != null) {
if (valueObject instanceof Double)
return ((Double)valueObject).doubleValue();
else if (valueObject instanceof Float)
return ((Float)valueObject).floatValue();
else if (valueObject instanceof Integer)
return ((Integer)valueObject).intValue();
else if (valueObject instanceof Byte)
return ((Byte)valueObject).byteValue();
else if (valueObject instanceof String)
return (String)valueObject;
}
return null;
}
在表格初始化的代码中,您需要添加以下内容:
myTable.setDefaultEditor(Float.class, new TextFieldCellEditor(new TextFieldCell(myTable), Float.class));
myTable.setDefaultEditor(Double.class, new TextFieldCellEditor(new TextFieldCell(myTable), Double.class));
myTable.setDefaultEditor(Integer.class, new TextFieldCellEditor(new TextFieldCell(myTable), Integer.class));
希望这能帮助遇到同样问题的人。