Java: where is source of unwanted behavior in my JFormattedTextField?

南笙酒味 提交于 2019-12-11 09:17:59

问题


My current Java project requires me to work with dates and through my research and tinkering around I discovered the setLenient() method is defaulted to true. When I set it to false I begin to have problems with my code.

I have a JFormattedTextField intialized with a SimpleDateFormat. For my project, I need to have / placeholders always present so using the answer to this question, I was able to install /s as place holders in the form of MM/dd/yyyy

When the SimpleDateFormat is set to setLenient(false), and an incomplete date is entered (such as 12/34/5), and then have the focus shift away from the formatted textfield, the entire field including the /s is removed.

When SimpleDateFormat is set to setLenient(true), this doesn't happen. Instead, the incomplete entry of 12/34/5 is set to 01/03/0006 once focus is lost.

I need to be able to usesetLenient(false) on my simple date formatter while also always having / placeholders. I do not really know where the core issue lies in the unwanted behavior of the program and would appreciate any insight.

Simplified program concerning issue:

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:


You can use an InputVerifier that will verify the contents. If the date is not valid, you can popup a JOptionPane.

See the example below. I try to parse the input in the method isValidDate. If it's not a valid date, it will return false, causing the InputVerifier to return false in it's verify method.

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();
            }
        });

    }
}


来源:https://stackoverflow.com/questions/22914371/java-where-is-source-of-unwanted-behavior-in-my-jformattedtextfield

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!