Получите JFormattedText действительное значение как можно скорее
Я хочу, чтобы текстовое поле позволяло пользователю вводить дату по определенному шаблону, и я хочу, чтобы эта дата возвращалась, как только она будет напечатана и действительна, то есть не дожидаясь, пока пользователь нажмет клавишу возврата в текстовом поле, чтобы обработать ее. Также я добавляю визуальные подсказки, является ли введенная дата правильной (изменение цвета фона текстового поля).
Вот пример SSC-не-правильный
package gui.date;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class DateEditor extends JFormattedTextField
{
public DateEditor()
{
this(null, null);
}
public DateEditor(Date d)
{
this(d, null);
}
public DateEditor(Date d, String pattern)
{
super(new SimpleDateFormat(pattern));
setValue(d);
setFocusLostBehavior(JFormattedTextField.PERSIST);
final Color origBgdColor = getBackground();
final Color wrongInputColor = new Color(0.8f, .0f, .0f);
final Color missingInputColor = new Color(1f, 1f, .65f);
if(d == null)
{
setColumns(10);
setBackground(missingInputColor);
}
addCaretListener(new CaretListener()
{
@Override
public void caretUpdate(CaretEvent e)
{
if(isEditValid())
{
try
{
setBackground(origBgdColor);
commitEdit();
}
catch(ParseException ex)
{
ex.printStackTrace();
}
}
else
{
try
{
String text = getText();
if(text.isEmpty())
setBackground(missingInputColor);
else
setBackground(wrongInputColor);
}
catch(NullPointerException ex)
{
setBackground(missingInputColor);
}
}
}
});
}
public Date getDate()
{
return (Date)getValue();
}
public void setDate(Date d)
{
setValue(d);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
final Date[] date = new Date[] { null }; // the date entered by the user should be filled here as soon as it is a valid date
final String pattern = "dd/MM/YYYY";
final SimpleDateFormat fm = new SimpleDateFormat(pattern);
JButton b = new JButton(new AbstractAction("Print value")
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
System.out.println(fm.format(date[0]));
}
catch(NullPointerException ex)
{
System.out.println("No date set yet");
}
}
});
final DateEditor d = new DateEditor(null, pattern);
d.addPropertyChangeListener("value", new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if(evt.getSource().equals(d))
{
date[0] = d.getDate();
}
}
});
final JFrame f = new JFrame(getClass().getName());
Container c = f.getContentPane();
c.setLayout(new FlowLayout());
c.add(b);
c.add(d);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
}
}
Если вы попробуете это, вы увидите несколько ошибок: 1/ Заданный шаблон, кажется, не применяется FormattedText, так что введенная действительная дата может быть преобразована в другую дату, когда я нажимаю ввод
2/ ParseException продолжает вызываться при вызове commitEdit в CaretListener, несмотря на то, что я сначала проверяю isEditValid()
!
Спасибо за вашу помощь.