【发布时间】:2018-07-01 07:51:33
【问题描述】:
我正在尝试编写一个 TableCellEditor 来验证 JTable 单元格的输入。我让它工作,除了错误消息显示两次。这是我的测试类:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class Tester {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setPreferredSize(new Dimension(500,100));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model=new DefaultTableModel(null,new String[] {"Col 1","Col 2"});
JTable table=new JTable(model);
table.getColumnModel().getColumn(0).setCellEditor(new decimalCellEditor());
model.insertRow(0,new Object[] {null,null});
JScrollPane scroller=new JScrollPane(table);
frame.add(scroller);
frame.setVisible(true);
frame.pack();
}
}
这是编辑器:
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;
public class DecimalCellEditor extends AbstractCellEditor implements TableCellEditor {
/**
*
*/
private static final long serialVersionUID = 1L;
private JTextField number=null;
public DecimalCellEditor() {
number=new JTextField();
}
@Override
public Object getCellEditorValue() {
String s=number.getText();
if (s.equals("")) {
return(s);
}
double x=0.;
try {
x=Double.parseDouble(s);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null,"Value must be numeric",null, JOptionPane.ERROR_MESSAGE, null);
return("");
}
return(Double.toString(x));
}
@Override
public Component getTableCellEditorComponent(JTable table_, Object value_, boolean isSelected_, int row_, int column_) {
number.setText(String.valueOf(value_));
return(number);
}
@Override
public boolean stopCellEditing() {
String s=(String) getCellEditorValue();
if (s.equals("")) {
return(super.stopCellEditing());
}
try {
Double.parseDouble(s);
} catch (NumberFormatException e) {
fireEditingCanceled();
return(false);
}
return(super.stopCellEditing());
}
}
目标是确保用户输入数字值或根本不输入值 ("")。是什么导致错误在非数字时显示和消除两次,我该如何阻止它? TIA。
实施camickr的建议
假设我理解了建议,我不需要编辑器?
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Tester {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setPreferredSize(new Dimension(500,100));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyTableModel model=new MyTableModel(null,new String[] {"Col 1","Col 2"});
JTable table=new JTable(model);
model.insertRow(0,new Object[] {"",""});
JScrollPane scroller=new JScrollPane(table);
frame.add(scroller);
frame.setVisible(true);
frame.pack();
}
}
覆盖 getColumnClass:
import javax.swing.table.DefaultTableModel;
public class MyTableModel extends DefaultTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
public MyTableModel(Object[][] data_,String[] columnNames_) {
super(data_,columnNames_);
}
@Override
public Class<?> getColumnClass(int column_) {
if (column_==0) {
return(Double.class);
}
return(getValueAt(0,column_).getClass());
}
}
我显然没有这样做,因为我从一个未知来源得到异常说:
线程“AWT-EventQueue-0”java.lang.IllegalArgumentException 中的异常:无法将给定对象格式化为数字
我猜我的构造函数有问题。
【问题讨论】:
-
可能
getCellEditorValue被多次调用......就像在stopCellEditing()和可能来自JTable。我会尽量不在stopCellEditing()中使用它,直接从文本字段中获取文本(如getCellEditorValue()中所做的那样) -
谢谢,但没用。它根本没有显示错误,这意味着
getCellEditorValue未被调用。 -
The objective is to assure the user enters a numeric value or no value at all ("").- 只需覆盖 TableModel 的getColumnClass(...)方法以返回列的Double.class,JTable 将使用适当的编辑器。单元格周围将放置一个红色边框,在解决问题之前您将无法保存数据。此外,类名应以大写字符开头。遵循 Java 约定! -
另外,为什么要将列的渲染器设置为新的 DefaultCellRenderer?教程曾经这样做过吗?无需实现整个编辑器界面。从 DefaultCellEditor 开始并自定义一些方法。查看:stackoverflow.com/questions/20390445/… 的自定义编辑器示例,当数据不正确时会显示错误消息。
-
我认为我没有完全理解这个建议。我用我的新代码更新了 OP。
标签: java swing jtable tablecelleditor