问题
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
andm
to appear as plain text (I tried escaping)- The number of hours has a max
*: See @nanda\'s answer
回答1:
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);
}
回答2:
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);
}
}
回答3:
Have you tried H'h' mm'm'
?
回答4:
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...
回答5:
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?
- Java SE 8 and SE 9 and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
- See How to use ThreeTenABP….
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.
来源:https://stackoverflow.com/questions/2234726/jformattedtextfield-input-time-duration-value