Java: где источник нежелательного поведения в моем JFormattedTextField?
Мой текущий Java-проект требует, чтобы я работал с датами, и благодаря моим исследованиям и поискам я обнаружил, что setLenient()
метод по умолчанию true
, Когда я установил его на false
У меня начинаются проблемы с моим кодом.
у меня есть JFormattedTextField
инициализирован с SimpleDateFormat
, Для моего проекта мне нужно иметь /
заполнители всегда присутствуют, поэтому, используя ответ на этот вопрос, я смог установить /
S в качестве заполнителей в виде MM/dd/yyyy
Когда SimpleDateFormat
установлен в setLenient(false)
и вводится неполная дата (например, 12/34/5), а затем смещение фокуса от форматированного текстового поля, все поле, включая /
с удаляется.
когда SimpleDateFormat
установлен в setLenient(true)
этого не происходит. Вместо этого неполная запись от 12/34/5 устанавливается на 01/03/0006
как только фокус потерян.
Мне нужно уметь пользоватьсяsetLenient(false)
на моем простом форматере даты, а также всегда с /
заполнители. Я действительно не знаю, где основная проблема заключается в нежелательном поведении программы, и был бы признателен за любую информацию.
Упрощенная программа по вопросу:
public class Hello implements ActionListener{
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
private Date endingDate = new Date();
private String endingString = null;
private SimpleDateFormat dateFormatter = new SimpleDateFormat("MM/dd/yyyy");
private JFormattedTextField formattedText = new JFormattedTextField(dateFormatter);
private JLabel label1 = new JLabel();
private JLabel label2 = new JLabel();
private TextArea ta = new TextArea();
private Button b = new Button("click");
public Hello() {
//setPreferredSize(new Dimension(500,500));
b.addActionListener(this);
label1 = new JLabel("test");
label2 = new JLabel("test");
formattedText.setColumns(10);
dateFormatter.setLenient(false); // not efficient
try {
MaskFormatter dateMask = new MaskFormatter("##/##/####");
dateMask.install(formattedText);
} catch (ParseException ex) {
Logger.getLogger(Hello.class.getName()).log(Level.SEVERE, null, ex);
}
panel.add(formattedText);
panel.add(label1);
panel.add(label2);
panel.add(ta);
panel.add(b);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new Hello();
}
});
System.out.println("Hello, World");
}
public void actionPerformed(ActionEvent e) {
System.out.println("Action performed");
System.out.println(formattedText);
endingDate = (Date) formattedText.getValue();
System.out.println(endingDate);
endingString = dateFormatter.format(endingDate);
System.out.println(endingString);
}
}
1 ответ
Вы можете использовать InputVerifier
это проверит содержимое. Если дата недействительна, вы можете открыть окно JOptionPane.
Смотрите пример ниже. Я пытаюсь разобрать вход в методе isValidDate
, Если это недействительная дата, она вернет false, вызывая InputVerifier
вернуть ложь в это verify
метод.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.text.MaskFormatter;
public class InputVerifyDate {
private SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
public InputVerifyDate() {
JFormattedTextField formattedField = createFormattedTextField();
JTextField field = new JTextField(10);
format.setLenient(false);
Box box = Box.createVerticalBox();
box.add(formattedField);
box.add(Box.createVerticalStrut(10));
box.add(field);
box.setBorder(new EmptyBorder(10, 10, 10, 10));
JFrame frame = new JFrame();
frame.add(box);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JFormattedTextField createFormattedTextField() {
JFormattedTextField formattedField = null;
try {
MaskFormatter dateMask = new MaskFormatter("##/##/####");
formattedField = new JFormattedTextField(dateMask);
} catch (ParseException ex) {
Logger.getLogger(InputVerifyDate.class.getName()).log(Level.SEVERE, null, ex);
}
formattedField.setColumns(10);
formattedField.setInputVerifier(getInputVerifier());
return formattedField;
}
private InputVerifier getInputVerifier() {
InputVerifier verifier = new InputVerifier() {
@Override
public boolean verify(JComponent input) {
JFormattedTextField field = (JFormattedTextField) input;
String text = field.getText();
return isValidDate(text);
}
@Override
public boolean shouldYieldFocus(JComponent input) {
boolean valid = verify(input);
if (!valid) {
JOptionPane.showMessageDialog(null, "Please enter a valid date in format dd/mm/yyyy");
}
return valid;
}
};
return verifier;
}
public boolean isValidDate(String dateString) {
try {
format.parse(dateString);
return true;
} catch (ParseException ex) {
return false;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new InputVerifyDate();
}
});
}
}