我正在尝试为jtable创建输入验证程序(格式HH:mm)。我尝试使用KeyListeners和TableModelListener,最后决定最佳解决方案是自定义单元格编辑器。
到目前为止,这是我的代码:
public class DateEditor extends DefaultCellEditor {
private JFormattedTextField textField;
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm");
public DateEditor() {
super( new JFormattedTextField() );
textField = (JFormattedTextField) getComponent();
textField.setFormatterFactory( new DefaultFormatterFactory( new DateFormatter(TIME_FORMAT) ) );
textField.setFocusLostBehavior( JFormattedTextField.PERSIST );
textField.getInputMap().put( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ), "check" );
textField.getActionMap().put( "check", new AbstractAction() {
public void actionPerformed( ActionEvent e ) {
if ( !textField.isEditValid() ) { //The text is invalid.
if ( userSaysRevert() ) { //reverted
textField.postActionEvent(); //inform the editor
}
}
else {
try { //The text is valid,
textField.commitEdit(); //so use it.
textField.postActionEvent(); //stop editing
}
catch ( java.text.ParseException exc ) {
}
}
}
} );
}
public Component getTableCellEditorComponent( JTable table,
Object value, boolean isSelected,
int row, int column ) {
JFormattedTextField ftf = (JFormattedTextField) super.getTableCellEditorComponent( table, value, isSelected, row, column );
ftf.setValue( value );
return ftf;
}
public Object getCellEditorValue() {
JFormattedTextField ftf = (JFormattedTextField) getComponent();
Object o = ftf.getValue();
System.out.println( "trying to parse date: " + o.getClass() );
if ( o instanceof Date ) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
System.out.println("Datum: " + simpleDateFormat.format(o));
return simpleDateFormat.format(o);
}
else if ( o instanceof String ) {
try {
return TIME_FORMAT.parse( o.toString() );
}
catch ( ParseException e ) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return new Date();
}
}
else {
new RuntimeException( "What type: " + o.getClass() ).printStackTrace();
return new Date();
}
}
public boolean stopCellEditing() {
JFormattedTextField ftf = (JFormattedTextField) getComponent();
if ( ftf.isEditValid() ) {
try {
ftf.commitEdit();
}
catch ( java.text.ParseException exc ) {
}
}
else { //text is invalid
if ( !userSaysRevert() ) { //user wants to edit
return false; //don't let the editor go away
}
}
return super.stopCellEditing();
}
protected boolean userSaysRevert() {
Toolkit.getDefaultToolkit().beep();
textField.selectAll();
Object[] options = {"Ändern",
"Abbrechen"};
int answer = JOptionPane.showOptionDialog(
SwingUtilities.getWindowAncestor( textField ),
"Die Zeit muss im Format hh:mm eingegeben werden",
"Falsches Eingabeformat",
JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
options,
options[1] );
if ( answer == 1 ) { //Revert!
textField.setValue(textField.getValue());
return true;
}
return false;
}
}
如果输入为157:30 ftf.isEditValid()显然为真,编辑后的值为13:30。但它应该是假的,因为157:30不是HH的有效时间:mm。下次我点击同一个单元格时会抛出以下错误:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Cannot format given Object as a Date
at java.base/java.text.DateFormat.format(Unknown Source)
at java.base/java.text.Format.format(Unknown Source)
at java.desktop/javax.swing.text.InternationalFormatter.valueToString(Unknown Source)
at java.desktop/javax.swing.JFormattedTextField$AbstractFormatter.install(Unknown Source)
at java.desktop/javax.swing.text.DefaultFormatter.install(Unknown Source)
at java.desktop/javax.swing.text.InternationalFormatter.install(Unknown Source)
at java.desktop/javax.swing.JFormattedTextField.setFormatter(Unknown Source)
at java.desktop/javax.swing.JFormattedTextField.setValue(Unknown Source)
at java.desktop/javax.swing.JFormattedTextField.setValue(Unknown Source)
at DateEditor.getTableCellEditorComponent(DateEditor.java:57)
...
Code-Line 57: ftf.setValue( value );
我需要在代码中更改哪些内容才能进行正确验证?