JFormattedTextField : input time duration value

bguiz picture bguiz · Feb 10, 2010 · Viewed 13.6k times · Source

I want to use a JFormattedTextField to allow the user to input time duration values into a form. Sample valid values are:

2h 30m
72h 15m
6h
0h

However I am having limited success with this. Can some one please suggest how this can be accomplished? I am OK if this result can be achieved using a JTextField as well.

Thanks!


If it is worth anything, here's my current attempt:

 mFormattedText.setFormatterFactory(
    new DefaultFormatterFactory(
        new DateFormatter(
            new SimpleDateFormat("H mm"))));

This sorta works except that:

  • I cannot get h and m to appear as plain text (I tried escaping) *
  • The number of hours has a max

*: See @nanda's answer

Answer

trashgod picture trashgod · Feb 11, 2010

Here's an example of using InputVerifier to accommodate multiple input formats.

import java.awt.EventQueue;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.Box;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatterFactory;

public class FormattedFields {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            //@Override
            public void run() {
                new FormattedFields();
            }
        });
    }

    FormattedFields() {
        Box form = Box.createVerticalBox();

        form.add(new JLabel("Date & Time:"));
        DateTimeField dtField = new DateTimeField(new Date());
        form.add(dtField);

        form.add(new JLabel("Amount:"));
        JFormattedTextField amtField = new JFormattedTextField(
            NumberFormat.getCurrencyInstance());
        amtField.setValue(100000);
        form.add(amtField);

        JFrame frame = new JFrame();
        frame.add(form);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

class DateTimeField extends JFormattedTextField {

    public DateTimeField() {
        super(DateTimeVerifier.getDefaultFormat());
        this.setInputVerifier(new DateTimeVerifier(this));
    }

    public DateTimeField(Date date) {
        this();
        this.setValue(date);
    }

    @Override
    protected void invalidEdit() {
        if (!this.getInputVerifier().verify(this)) {
            super.invalidEdit();
        }
    }
}

class DateTimeVerifier extends InputVerifier {

    private static List<SimpleDateFormat> validForms =
        new ArrayList<SimpleDateFormat>();


    static {
        validForms.add(new SimpleDateFormat("dd-MMM-yyyy HH'h':mm'm'"));
        validForms.add(new SimpleDateFormat("dd-MMM-yyyy HH:mm"));
    }
    private JFormattedTextField tf;
    private Date date;

    public DateTimeVerifier(JFormattedTextField tf) {
        this.tf = tf;
    }

    @Override
    public boolean verify(JComponent input) {
        boolean result = false;
        if (input == tf) {
            String text = tf.getText();
            for (SimpleDateFormat format : validForms) {
                try {
                    date = format.parse(text);
                    result |= true;
                } catch (ParseException pe) {
                    result |= false;
                }
            }
        }
        return result;
    }

    @Override
    public boolean shouldYieldFocus(JComponent input) {
        if (verify(input)) {
            tf.setValue(date);
            return true;
        } else {
            return false;
        }
    }

    public static SimpleDateFormat getDefaultFormat() {
        return validForms.get(0);
    }
}