JFormattedTextField:输入持续时间值

时间:2010-02-10 05:48:55

标签: java time jtextfield duration jformattedtextfield

我想使用JFormattedTextField来允许用户在表单中输入 duration 值。示例有效值为:

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

然而,我在这方面的成功有限。有人可以建议如何实现这一目标吗?如果使用JTextField也可以实现此结果,我很好。

谢谢!


如果它有价值,这是我目前的尝试:

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

除了:

之外,这种方法有效
  • 我无法将hm显示为纯文本(我尝试转义) *
  • 小时数最多

*:请参阅@ nanda的回答

5 个答案:

答案 0 :(得分:4)

以下是使用InputVerifier来容纳多种输入格式的示例。

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

答案 1 :(得分:1)

您是否尝试过H'h' mm'm'

答案 2 :(得分:1)

代码:

public static void main(String[] args) {
    JFrame jFrame = new JFrame();
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.setLayout(new BorderLayout());
    jFrame.setPreferredSize(new Dimension(500, 500));

    final JFormattedTextField comp = new JFormattedTextField();
    comp.setFormatterFactory(new DefaultFormatterFactory(new DateFormatter(new SimpleDateFormat(
            "H'h' mm'm'"))));
    comp.setValue(Calendar.getInstance().getTime());

    comp.addPropertyChangeListener("value", new PropertyChangeListener() {

        @Override public void propertyChange(PropertyChangeEvent evt) {
            System.out.println(comp.getValue());

        }
    });

    jFrame.getContentPane().add(comp, BorderLayout.CENTER);

    jFrame.pack();
    jFrame.setVisible(true);
}

答案 3 :(得分:0)

嗯,我认为你可以达到同样的目标,为所有三个时间组件创建三个不同的JTextField,一个用于HOUR,MINUTE和Second(如果它包括在内)来获取你的输入......一个想法,如果你有必要,你可以将它们连接起来......只是一个想法...

答案 4 :(得分:0)

TL;博士

Duration.parse( "PT2H30M" )

ISO 8601

如果您愿意重新定义所需的输入格式,我建议您使用ISO 8601标准定义的现有格式。

模式PnYnMnDTnHnMnS使用P标记开头,T将任意年 - 月 - 日部分与任何小时 - 分 - 秒部分分开。

例如,一小时是PT1H30M

java.time

在解析/生成字符串时,java.time类默认使用ISO 8601格式。这包括PeriodDuration类,用于表示未附加到时间轴的时间跨度。

Duration d = Duration.ofHours( 1 ).plusMinutes( 30 );
String output = d.toString();

转向另一个方向,解析一个字符串。

Duration d = Duration.parse( "PT1H30M" );

请参阅live code in IdeOne.com

请参阅my similar Answersimilar Question

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore