I am using couple of JSpinners in my project who display the hour and minutes. When the JSpinner is incremented or decremented i have to save the value to the database. But the problem is that the JSpinners are giving me old values.
eg- If the time displayed is 09:30
and i increment the time to 10:30
, I am getting 09:30 as the returned value. I am using following code
UPDATED SSCCE
package spinnerupdation;
import java.awt.Container;
import java.awt.FlowLayout;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatterFactory;
/**
*
* @author Rohan Kandwal
*/
public class SpinnerUpdation extends JFrame{
public JSpinner spinner;
SpinnerUpdation(){
Container pane=this.getContentPane();
JPanel panel=new JPanel();
panel.setLayout(new FlowLayout());
SpinnerDateModel model=new SpinnerDateModel();
model.setCalendarField(Calendar.HOUR);
spinner=new JSpinner();
spinner.setModel(model);
spinner.setEditor(new JSpinner.DateEditor(spinner,"hh:mm"));
panel.add(spinner);
pane.add(panel);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
JFormattedTextField tf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
DefaultFormatterFactory factory = (DefaultFormatterFactory) tf.getFormatterFactory();
DateFormatter formatter = (DateFormatter) factory.getDefaultFormatter();
// Change the date format to only show the hours
formatter.setFormat(new SimpleDateFormat("hh:mm"));
//formatter.setCommitsOnValidEdit(true);
System.out.println(spinner.getValue());
//System.out.println(tf.getText());
}
});
}
public static void main(String[] args) {
SpinnerUpdation ss=new SpinnerUpdation();
ss.setDefaultCloseOperation(ss.EXIT_ON_CLOSE);
ss.setSize(574, 445);
//ss.pack();
ss.setLocationRelativeTo(null);
ss.setResizable(false);
ss.setVisible(true);
}
}
if i am using tf.getText()
i am getting the old value twice but if i am using spinner.getValue
I am getting the new value but it is in long format
Thu Jan 01 10:18:00 IST 1970
Thu Jan 01 11:18:00 IST 1970
How should i format spinner to give only 11:18
?
Java swing use a MVC pattern, so it is the same in JSpinner. If you look into JSpinner source code, you will find that the getValue() method is actually call getModel().getValue(), so it is calling the model's getValue. and the model you use is SpinnerDateModel, and the value of it will be Date Object,when you print the Date object, it will display the default format like "Thu Jan 01 11:18:00 IST 1970", if your want to get something like "11:18", you will need to format it yourself.like
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm");
System.out.println(sdf.format(spinner.getValue()) );
You may wonder why tf.getText() only get the old value, because after the ChangeEvent on the spinner occurs, a PropertyChangeEvent on the tf will occurs,will set the new value to it. Of course, you can listen to tf like tf.addPropertyChangeListener. but i will suggest use the solution above.
You could maintain a "master date" which you re-merge the time value back into on each stateChanged
event.
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
add(new DateSpinner(new Date()));
}
}
public class DateSpinner extends JSpinner {
private Date masterDate;
public DateSpinner(Date date) {
super(new SpinnerDateModel());
this.masterDate = date;
SpinnerDateModel model = (SpinnerDateModel) getModel();
model.setCalendarField(Calendar.HOUR);
setEditor(new JSpinner.DateEditor(this, "hh:mm"));
JFormattedTextField tf = ((JSpinner.DefaultEditor) getEditor()).getTextField();
DefaultFormatterFactory factory = (DefaultFormatterFactory) tf.getFormatterFactory();
DateFormatter formatter = (DateFormatter) factory.getDefaultFormatter();
formatter.setFormat(new SimpleDateFormat("hh:mm"));
setValue(date);
addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Calendar cal = Calendar.getInstance();
cal.setTime(masterDate);
Calendar time = Calendar.getInstance();
time.setTime((Date) getValue());
cal.set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY));
cal.set(Calendar.MINUTE, time.get(Calendar.MINUTE));
masterDate = cal.getTime();
System.out.println(masterDate);
}
});
}
public String getTime() {
return new SimpleDateFormat("hh:mm").format((Date)getValue());
}
}
}
来源:https://stackoverflow.com/questions/14451449/jspinner-giving-old-values