Problem 1: User can edited hour minutes and second seperator ":" and
can write extra digits like "123"
You can use the editor's formatter to accomplish this through getTextField() method:
JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, "HH:mm:ss");
DateFormatter formatter = (DateFormatter)editor.getTextField().getFormatter();
formatter.setAllowsInvalid(false); // this makes what you want
formatter.setOverwriteMode(true);
The text field is in fact a JFormattedTextField with a DateFormatter as formatter. Take a look to How to Use Formatted Text Fields for a better understanding on how to work with this component.
Note the pattern used when the editor is created. It's "HH:mm:ss" because of your 2nd requirement.
Problem 2: model get always current time. I want "00:00:00"
You need to provide to your spinner with an initial date at 12 PM (24 hours) which will be translated in "00:00:00":
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 24);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
SpinnerDateModel model = new SpinnerDateModel();
model.setValue(calendar.getTime());
JSpinner spinner = new JSpinner(model);
Example
Here is a quite simple example to test what I've said. Hope it be helpful.
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SwingUtilities;
import javax.swing.text.DateFormatter;
public class Demo {
private void createAndShowGUI() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 24); // 24 == 12 PM == 00:00:00
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
SpinnerDateModel model = new SpinnerDateModel();
model.setValue(calendar.getTime());
JSpinner spinner = new JSpinner(model);
JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, "HH:mm:ss");
DateFormatter formatter = (DateFormatter)editor.getTextField().getFormatter();
formatter.setAllowsInvalid(false); // this makes what you want
formatter.setOverwriteMode(true);
spinner.setEditor(editor);
JPanel content = new JPanel();
content.add(spinner);
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
Edit
When user try manually write hours or minutes (not using arrows) some
logical problem ocures i think. Example i write 12 but spinner shows
21.
First off sorry I didn't note that before. This creepy behaviour happens because formatter's overwrite mode property is set to false
somewhere during JSpinner.DateEditor
's initialization (but couldn't find where). This property is true
by default according to javadoc. To solve this you only need to add this line (I've also edited my code above):
formatter.setOverwriteMode(true);
Calendar
and setting the hour, minute and seconds fields to 0 and setting the spinners value to the resultDate
returned byCalendar#getTime
– Crossstaff