JFormattedTextField :输入持续时间值

发布于 2024-08-21 01:36:26 字数 627 浏览 6 评论 0原文

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

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

但是我在这方面取得的成功有限。有人可以建议如何实现这一目标吗?如果使用 JTextField 也能实现此结果,我就可以了。

谢谢!


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

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

这种方法有效,除了:

  • 我无法让 hm 显示为纯文本(我尝试转义) *
  • 小时数有上限

*:参见 @nanda 的回答

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

反目相谮 2024-08-28 01:36:26

下面是使用 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);
    }
}

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);
    }
}
纵性 2024-08-28 01:36:26

代码:

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

The code:

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);
}
呆橘 2024-08-28 01:36:26

您尝试过H'h'mm'm'吗?

Have you tried H'h' mm'm'?

故事还在继续 2024-08-28 01:36:26

嗯,我认为您可以通过为所有三个时间组件创建三个不同的 JTextField 来实现相同的目标,一个用于小时、分钟和秒(如果包含的话)来获取您的输入...只是一个想法,如果有必要的话,你可以将它们连接起来......只是一个想法......

hmm, what i think is that you can achieve the same goal by, creating three different JTextField for all the three time components, one for the HOUR, MINUTE and Second (if it's included) to get your input... just a thought, you could just concatenate them if you it's necessary... just a thought...

甩你一脸翔 2024-08-28 01:36:26

tl;dr

Duration.parse( "PT2H30M" )

ISO 8601

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

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

例如,一个半小时是 PT1H30M

java.time

java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。这包括 期间< /a> 和 持续时间 用于表示未附加到时间线的时间跨度的类。

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

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

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

请参阅IdeOne.com 中的实时代码

请参阅我对的类似答案类似的问题。


关于 java.time

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

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

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如 间隔YearWeek<代码>YearQuarter,以及更多

tl;dr

Duration.parse( "PT2H30M" )

ISO 8601

If you are willing to redefine your desired input formats, I suggest using the already-existing formats defined by the ISO 8601 standard.

The pattern PnYnMnDTnHnMnS uses a P to mark the beginning, a T to separate any years-months-days portion from any hours-minutes-seconds portion.

An hour-and-a-half is PT1H30M, for example.

java.time

The java.time classes use the ISO 8601 formats by default when parsing/generating strings. This includes the Period and Duration classes for representing spans of time not attached to the timeline.

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

Going the other direction, parsing a string.

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

See live code in IdeOne.com.

See my similar Answer to a similar Question.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文