JSpinner 跳跃数周而不是数天
JSpinner jumping weeks rather than days
我创建了一个 JSpinner 对象,它每天上下移动,点击时跳过周末。然后我添加了一个功能,如果你在周六或周日打开程序,它应该回滚到周五。问题不是改为星期五,而是 JSpinner 跳回一周。
我尝试在新程序中隔离问题,但没有成功。代码应该完全相同,所以我不确定是什么导致了这个问题。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.annotation.PostConstruct;
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;
@SuppressWarnings("serial")
public class MainFrame extends JFrame {
DecimalFormat df = new DecimalFormat("#.00");
SpinnerDateModel spinnerModel;
JSpinner spinner;
Integer loopStep;
Integer firstloopStep = 0;
MainFrame() {
super("Spinner Control");
setLayout(new BorderLayout());
JPanel panel1 = new JPanel();
JPanel panelNorth = new JPanel();
// spinner for date information
spinnerModel = new SpinnerDateModel();
spinnerModel.setCalendarField(Calendar.WEEK_OF_MONTH);
spinner = new JSpinner(spinnerModel);
JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, "EEEEE, dd MMMMM, yyyy");
spinner.setEditor(editor);
// add panels/buttons/etc to page
add(panel1, BorderLayout.PAGE_START);
panel1.setPreferredSize(new Dimension(1280, 100));
panelNorth.setPreferredSize(new Dimension(1280, 40));
panel1.add(panelNorth, BorderLayout.NORTH);
panelNorth.add(spinner, BorderLayout.PAGE_START);
//method executes on start up
skipWeekends();
loopStep = 0;
//rotate the date, skip weekends, works fine here
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
Date date = (Date) spinner.getValue();
System.out.println("todays date " + date);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE, dd MMMMM, yyyy");
String stringDate = sdf.format(date);
System.out.println(stringDate);
char c = stringDate.charAt(0);
char c2 = stringDate.charAt(1);
//skip the weekends
if ((c == 'S') && (c2 == 'a') && (loopStep == 0)) {
loopStep = 1;
spinner.setValue(spinner.getNextValue());
spinner.setValue(spinner.getNextValue());
System.out.println("Saturday Spinner going back 2");
}
if ((c == 'S') && (c2 == 'u') && (loopStep == 0)) {
loopStep = 1;
spinner.setValue(spinner.getPreviousValue());
spinner.setValue(spinner.getPreviousValue());
System.out.println("Sunday Spinner going back 2");
}
if (loopStep == 1) {
loopStep = 2;
}
if (loopStep == 2) {
loopStep = 0;
}
}
});
setExtendedState(MAXIMIZED_BOTH);
setMinimumSize(new Dimension(1280, 485));
setSize(640, 485);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
@PostConstruct
private void skipWeekends(){
//skips weekends when program opens, skips weeks for some reason
Date date = (Date) spinner.getValue();
System.out.println("todays date " + date);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE, dd MMMMM, yyyy");
String stringDate = sdf.format(date);
System.out.println(stringDate);
char c = stringDate.charAt(0);
char c2 = stringDate.charAt(1);
if ((c == 'S') && (c2 == 'a')) {
spinner.setValue(spinner.getPreviousValue());
System.out.println("Saturday Spinner going back 2");
}
if ((c == 'S') && (c2 == 'u')) {
spinner.setValue(spinner.getPreviousValue());
spinner.setValue(spinner.getPreviousValue());
System.out.println("Sunday Spinner going back 2");
}
}
}
您正在将 SpinnerDateModel 的日历字段设置为 Calendar.WEEK_OF_MONTH 而不是 Calendar.DAY_OF_WEEK。
当使用 Spinner 按钮时,这个问题得到了无声更正,因为 Spinner 会在提交更改之前设置日历字段(这在 SpinnerDateModel 文档中提到)。不过,您的 @PostConstruct 方法在这有机会发生之前运行。
如果我可以添加另一个建议:您计算星期几的方法非常复杂且非常脆弱(例如在德国它会崩溃,因为 "Sunday" 是 "Sonntag"这里)。这是一个替代方案。在构造函数中用 initial == true 调用它,在 stateChanged() 中用 initial == false 调用它。
private Calendar cal = new GregorianCalendar();
private void skipWeekends(boolean initial) {
cal.setTime(spinnerModel.getDate());
switch (cal.get(Calendar.DAY_OF_WEEK)) {
case Calendar.SATURDAY:
cal.add(Calendar.DAY_OF_WEEK, initial ? -1 : 2);
break;
case Calendar.SUNDAY:
cal.add(Calendar.DAY_OF_WEEK, -2);
break;
}
spinnerModel.setValue(cal.getTime());
}
我认为您需要 select 当前日历字段,然后它将受到 JSpinner 的 getNextValue()
和 getPreviousValue()
方法的影响。
要制造select离子,您可以使用:
spinner.setCalendarField(Calendar.DAY_OF_YEAR);
我创建了一个 JSpinner 对象,它每天上下移动,点击时跳过周末。然后我添加了一个功能,如果你在周六或周日打开程序,它应该回滚到周五。问题不是改为星期五,而是 JSpinner 跳回一周。
我尝试在新程序中隔离问题,但没有成功。代码应该完全相同,所以我不确定是什么导致了这个问题。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.annotation.PostConstruct;
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;
@SuppressWarnings("serial")
public class MainFrame extends JFrame {
DecimalFormat df = new DecimalFormat("#.00");
SpinnerDateModel spinnerModel;
JSpinner spinner;
Integer loopStep;
Integer firstloopStep = 0;
MainFrame() {
super("Spinner Control");
setLayout(new BorderLayout());
JPanel panel1 = new JPanel();
JPanel panelNorth = new JPanel();
// spinner for date information
spinnerModel = new SpinnerDateModel();
spinnerModel.setCalendarField(Calendar.WEEK_OF_MONTH);
spinner = new JSpinner(spinnerModel);
JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, "EEEEE, dd MMMMM, yyyy");
spinner.setEditor(editor);
// add panels/buttons/etc to page
add(panel1, BorderLayout.PAGE_START);
panel1.setPreferredSize(new Dimension(1280, 100));
panelNorth.setPreferredSize(new Dimension(1280, 40));
panel1.add(panelNorth, BorderLayout.NORTH);
panelNorth.add(spinner, BorderLayout.PAGE_START);
//method executes on start up
skipWeekends();
loopStep = 0;
//rotate the date, skip weekends, works fine here
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
Date date = (Date) spinner.getValue();
System.out.println("todays date " + date);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE, dd MMMMM, yyyy");
String stringDate = sdf.format(date);
System.out.println(stringDate);
char c = stringDate.charAt(0);
char c2 = stringDate.charAt(1);
//skip the weekends
if ((c == 'S') && (c2 == 'a') && (loopStep == 0)) {
loopStep = 1;
spinner.setValue(spinner.getNextValue());
spinner.setValue(spinner.getNextValue());
System.out.println("Saturday Spinner going back 2");
}
if ((c == 'S') && (c2 == 'u') && (loopStep == 0)) {
loopStep = 1;
spinner.setValue(spinner.getPreviousValue());
spinner.setValue(spinner.getPreviousValue());
System.out.println("Sunday Spinner going back 2");
}
if (loopStep == 1) {
loopStep = 2;
}
if (loopStep == 2) {
loopStep = 0;
}
}
});
setExtendedState(MAXIMIZED_BOTH);
setMinimumSize(new Dimension(1280, 485));
setSize(640, 485);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
@PostConstruct
private void skipWeekends(){
//skips weekends when program opens, skips weeks for some reason
Date date = (Date) spinner.getValue();
System.out.println("todays date " + date);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE, dd MMMMM, yyyy");
String stringDate = sdf.format(date);
System.out.println(stringDate);
char c = stringDate.charAt(0);
char c2 = stringDate.charAt(1);
if ((c == 'S') && (c2 == 'a')) {
spinner.setValue(spinner.getPreviousValue());
System.out.println("Saturday Spinner going back 2");
}
if ((c == 'S') && (c2 == 'u')) {
spinner.setValue(spinner.getPreviousValue());
spinner.setValue(spinner.getPreviousValue());
System.out.println("Sunday Spinner going back 2");
}
}
}
您正在将 SpinnerDateModel 的日历字段设置为 Calendar.WEEK_OF_MONTH 而不是 Calendar.DAY_OF_WEEK。
当使用 Spinner 按钮时,这个问题得到了无声更正,因为 Spinner 会在提交更改之前设置日历字段(这在 SpinnerDateModel 文档中提到)。不过,您的 @PostConstruct 方法在这有机会发生之前运行。
如果我可以添加另一个建议:您计算星期几的方法非常复杂且非常脆弱(例如在德国它会崩溃,因为 "Sunday" 是 "Sonntag"这里)。这是一个替代方案。在构造函数中用 initial == true 调用它,在 stateChanged() 中用 initial == false 调用它。
private Calendar cal = new GregorianCalendar();
private void skipWeekends(boolean initial) {
cal.setTime(spinnerModel.getDate());
switch (cal.get(Calendar.DAY_OF_WEEK)) {
case Calendar.SATURDAY:
cal.add(Calendar.DAY_OF_WEEK, initial ? -1 : 2);
break;
case Calendar.SUNDAY:
cal.add(Calendar.DAY_OF_WEEK, -2);
break;
}
spinnerModel.setValue(cal.getTime());
}
我认为您需要 select 当前日历字段,然后它将受到 JSpinner 的 getNextValue()
和 getPreviousValue()
方法的影响。
要制造select离子,您可以使用:
spinner.setCalendarField(Calendar.DAY_OF_YEAR);