JFormattedTextField:input持续时间值

我想使用JFormattedTextField来允许用户input时间值到表单中。 示例有效值是:

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

但是,我在这方面取得了有限的成功。 有人可以build议如何做到这一点? 如果使用JTextField也可以实现这个结果,我很好。

谢谢!


如果这是值得的,这是我目前的尝试:

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

这种工作除了:

  • 我不能让hm显示为纯文本(我尝试转义) *
  • 小时数有一个最大值

*:看@南达的答案

代码:

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

以下是使用InputVerifier来适应多种input格式的示例。

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

你试过H'h' mm'm'吗?

嗯,我认为你可以达到相同的目标,为所有三个时间组件创build三个不同的JTextField,一个用于HOUR,MINUTE和Second(如果包含)来获得您的input…只是一个想法,你可以把它们连接起来,如果你有必要的话…只是一个想法…

TL;博士

 Duration.parse( "PT2H30M" ) 

ISO 8601

如果你愿意重新定义你想要的input格式,我build议使用ISO 8601标准定义的已经存在的格式。

模式PnYnMnDTnHnMnS使用P来标记开始, T将任何年 – 月 – 日部分与任何小时 – 分钟 – 秒部分分开。

例如,一个半小时是PT1H30M

java.time

parsing/生成string时,java.time类默认使用ISO 8601格式。 这包括用于表示时间跨度不附加到时间轴上的PeriodDuration类。

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

去另一个方向,parsing一个string。

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

在IdeOne.com中查看实时代码 。

看到我的类似的问题 类似的答案 。


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧的遗留date时间类,如java.util.DateCalendarSimpleDateFormat

Joda-Time项目现在处于维护模式 ,build议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。 规范是JSR 310 。

从何处获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6SE 7
    • 大部分的java.timefunction都被移植到了ThreeTen-Backport中的 Java 6&7中。
  • Android的
    • ThreeTenABP项目专门针对Android,采用了ThreeTen-Backport (上文提到)。
    • 请参阅如何使用ThreeTenABP …。

ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 你可能会在这里find一些有用的类,比如IntervalYearWeekYearQuarter 等等 。