1. /**
  2. * <p>Copyright: Copyright (c) 2002-2004</p>
  3. * <p>Company: JavaResearch(http://www.javaresearch.org)</p>
  4. * <p>最后更新日期:2003年4月25日
  5. * @author Zhouzhq
  6. */
  7. package org.jr.swing;
  8. import java.util.*;
  9. import java.awt.*;
  10. import java.awt.event.*;
  11. import javax.swing.*;
  12. import javax.swing.border.*;
  13. import javax.swing.event.ChangeEvent;
  14. import javax.swing.event.ChangeListener;
  15. /**
  16. * 日期操作面板,以Windows的通用方式选择和设置日期。
  17. * @since 0.6
  18. */
  19. public final class DatePanel
  20. extends JPanel {
  21. private static ResourceBundle stringResource = ResourceBundle.getBundle(
  22. "org.jr.resources.DatePanelResource");
  23. private Calendar date = Calendar.getInstance();
  24. ;
  25. private int returnValue;
  26. private JLabel selectedDay; //the selected index of days---------------------
  27. //|
  28. private JComboBox month = new JComboBox(); //|
  29. private JSpinner year = new JSpinner(new SpinnerNumberModel(1, 1, 9999, 1)); //|
  30. private JButton up; //|
  31. private JButton down; //|
  32. private JLabel[] days = new JLabel[42]; //<----------------------------------
  33. private JButton ok = new JButton("OK");
  34. private JButton cancel = new JButton("Cancel");
  35. private JPanel panel;
  36. /**
  37. * 构造方法,生成面板。
  38. * @param okListener OK按钮的ActionListener(不可为空)
  39. * @param cancelListener Cancel按钮的ActionListener
  40. */
  41. public DatePanel(ActionListener okListener, ActionListener cancelListener) {
  42. JSpinner.NumberEditor yearEditor = new JSpinner.NumberEditor(year, "###0");
  43. year.setEditor(yearEditor);
  44. JPanel contentPanel = new JPanel();
  45. contentPanel.setLayout(new BorderLayout());
  46. panel = new JPanel(new BorderLayout());
  47. panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.
  48. createEtchedBorder(),
  49. stringResource.getString("date")));
  50. JPanel pn = new JPanel(new GridBagLayout()) {
  51. public Insets getInsets() {
  52. return new Insets(0, 0, 3, 0);
  53. }
  54. };
  55. GridBagConstraints gc = new GridBagConstraints();
  56. initMonth();
  57. gc.gridx = 0;
  58. gc.gridy = 0;
  59. gc.gridwidth = 1;
  60. gc.gridheight = 1;
  61. pn.add(month, gc);
  62. gc.gridx = 1;
  63. pn.add(Box.createRigidArea(new Dimension(5, 1)), gc);
  64. initYear();
  65. gc.gridx = 2;
  66. gc.weightx = 10;
  67. gc.fill = GridBagConstraints.HORIZONTAL;
  68. pn.add(year, gc);
  69. addDays(); //处历院责显示日期的\uFFFD?
  70. panel.add(pn, BorderLayout.NORTH);
  71. MyListener myListener = new MyListener();
  72. JPanel ps = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  73. ok.setMargin(new Insets(0, 6, 0, 6));
  74. ps.add(ok);
  75. cancel.setMargin(new Insets(0, 6, 0, 6));
  76. ps.add(cancel);
  77. ok.addMouseListener(myListener);
  78. contentPanel.add(ps, BorderLayout.SOUTH);
  79. contentPanel.add(panel, BorderLayout.CENTER);
  80. Dimension d = getSize();
  81. setSize(d.width + 10, d.height);
  82. initDateDialog();
  83. if (okListener == null) {
  84. throw new NullPointerException();
  85. }
  86. ok.addActionListener(okListener);
  87. cancel.addActionListener(cancelListener);
  88. add(contentPanel);
  89. }
  90. private void initYear() {
  91. year.setBorder(new EtchedBorder());
  92. year.addChangeListener(new YearListener());
  93. year.setPreferredSize(new Dimension(85, 22));
  94. year.setMaximumSize(new Dimension(85, 22));
  95. year.setMinimumSize(new Dimension(85, 22));
  96. }
  97. private void initMonth() {
  98. month.addItem(stringResource.getString("jan"));
  99. month.addItem(stringResource.getString("feb"));
  100. month.addItem(stringResource.getString("mar"));
  101. month.addItem(stringResource.getString("apr"));
  102. month.addItem(stringResource.getString("may"));
  103. month.addItem(stringResource.getString("jun"));
  104. month.addItem(stringResource.getString("jul"));
  105. month.addItem(stringResource.getString("aug"));
  106. month.addItem(stringResource.getString("sep"));
  107. month.addItem(stringResource.getString("oct"));
  108. month.addItem(stringResource.getString("nov"));
  109. month.addItem(stringResource.getString("dec"));
  110. month.setPreferredSize(new Dimension(90, 22));
  111. month.setMaximumSize(new Dimension(90, 22));
  112. month.setMinimumSize(new Dimension(90, 22));
  113. month.addActionListener(new MonthListener());
  114. }
  115. private void addDays() {
  116. DayListener dayListener = new DayListener();
  117. for (int i = 0; i < 42; i++) {
  118. days[i] = new JLabel(" ");
  119. days[i].setMaximumSize(new Dimension(15, 15));
  120. days[i].setPreferredSize(new Dimension(15, 15));
  121. days[i].setBackground(new Color(0, 0, 125));
  122. days[i].addMouseListener(dayListener);
  123. }
  124. JPanel dayPanel = new JPanel(new BorderLayout());
  125. dayPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
  126. JPanel dayPn = new JPanel(new GridLayout(1, 7, 5, 5));
  127. dayPn.setBackground(new Color(140, 140, 140));
  128. dayPn.add(new JLabel(stringResource.getString("sun"))).setForeground(new
  129. Color(222, 222, 222));
  130. dayPn.add(new JLabel(stringResource.getString("mon"))).setForeground(new
  131. Color(222, 222, 222));
  132. dayPn.add(new JLabel(stringResource.getString("tue"))).setForeground(new
  133. Color(222, 222, 222));
  134. dayPn.add(new JLabel(stringResource.getString("wed"))).setForeground(new
  135. Color(222, 222, 222));
  136. dayPn.add(new JLabel(stringResource.getString("thu"))).setForeground(new
  137. Color(222, 222, 222));
  138. dayPn.add(new JLabel(stringResource.getString("fri"))).setForeground(new
  139. Color(222, 222, 222));
  140. dayPn.add(new JLabel(stringResource.getString("sat"))).setForeground(new
  141. Color(222, 222, 222));
  142. dayPanel.add(dayPn, BorderLayout.NORTH);
  143. JPanel dayPc = new JPanel(new GridLayout(6, 7, 5, 5));
  144. dayPc.setBackground(new Color(255, 255, 255));
  145. for (int i = 0; i < 42; i++) {
  146. dayPc.add(days[i]);
  147. }
  148. dayPanel.add(dayPc, BorderLayout.CENTER);
  149. panel.add(dayPanel, BorderLayout.CENTER);
  150. }
  151. private int daysOfMonth(int year, int month) {
  152. //得出year年month月共有多少?
  153. int dayCount = 0; //days of the month
  154. switch (month) {
  155. case 0:
  156. case 2:
  157. case 4:
  158. case 6:
  159. case 7:
  160. case 9:
  161. case 11:
  162. //1,3,5,7,8,10,12月
  163. dayCount = 31;
  164. break;
  165. case 3:
  166. case 5:
  167. case 8:
  168. case 10:
  169. //4,6,9月
  170. dayCount = 30;
  171. break;
  172. case 1: //February
  173. Calendar c1 = Calendar.getInstance();
  174. c1.set(year, 1, 28); //2.28
  175. int week1 = c1.get(Calendar.DAY_OF_WEEK);
  176. Calendar c2 = Calendar.getInstance();
  177. c2.set(year, 2, 1); //3.1
  178. int week2 = c2.get(Calendar.DAY_OF_WEEK);
  179. if ( (week2 - week1) == 1 || (week2 - week1) == -6) { //interval one day
  180. dayCount = 28;
  181. }
  182. else {
  183. dayCount = 29;
  184. }
  185. break;
  186. }
  187. return dayCount;
  188. }
  189. private void initDateDialog() {
  190. processDays(date);
  191. int y = date.get(Calendar.YEAR); //?
  192. int m = date.get(Calendar.MONTH); //月
  193. year.setValue(new Integer(y));
  194. month.setSelectedIndex(m);
  195. }
  196. private void processDays(Calendar date) {
  197. int y = date.get(Calendar.YEAR); //?
  198. int m = date.get(Calendar.MONTH); //月
  199. int d = date.get(Calendar.DAY_OF_MONTH); //日
  200. int dayCount = daysOfMonth(y, m);
  201. for (int i = 0; i < 42; i++) { //clear days[]
  202. days[i].setText(" ");
  203. }
  204. Calendar c = Calendar.getInstance();
  205. c.set(y, m, 1);
  206. int week = c.get(Calendar.DAY_OF_WEEK); //得出该月一号是星期几 *星期日~~~星期六值为:1~~7
  207. for (int i = week - 1, day = 1; day <= dayCount; day++) {
  208. String s = "" + day;
  209. if (s.length() == 1) {
  210. s = " " + s;
  211. }
  212. days[i++].setText(s);
  213. }
  214. if (selectedDay != null) {
  215. selectedDay.setOpaque(false); //通?朔椒ㄊ筨ackground可?
  216. selectedDay.setForeground(new Color(0, 0, 0));
  217. }
  218. selectedDay = days[d + week - 2]; //d+week-2是当前日期在days?榈奈恢?
  219. selectedDay.setOpaque(true); //通?朔椒ㄊ筨ackground可?
  220. selectedDay.setForeground(new Color(255, 255, 255));
  221. }
  222. /**
  223. * 获得用户指定的Date的对象。
  224. * @return Date对象
  225. * @since 0.1
  226. */
  227. public Date getDate() {
  228. return date.getTime();
  229. }
  230. /**
  231. * 获得用户指定的Calendar的克隆对象。
  232. * @return Calendar对象
  233. * @since 0.1
  234. */
  235. public Calendar getCalendar() {
  236. return (Calendar) date.clone();
  237. }
  238. //====== inner class MyActionListener =====
  239. /**
  240. * 内部类,负责在okListener前正确的得到用户选择的日期。
  241. */
  242. private class MyListener
  243. extends MouseAdapter {
  244. public void mousePressed(MouseEvent e) {
  245. if (e.getSource() == ok) {
  246. Calendar c = Calendar.getInstance();
  247. int y = ( (Integer) year.getValue()).intValue();
  248. int m = month.getSelectedIndex();
  249. int d = Integer.parseInt(selectedDay.getText().trim());
  250. c.set(y, m, d);
  251. date = c;
  252. }
  253. }
  254. }
  255. /**
  256. * 内部类,负责在日期面板的‘天’的处理。
  257. */
  258. private class DayListener
  259. extends MouseAdapter {
  260. public void mousePressed(MouseEvent e) {
  261. JLabel label = (JLabel) e.getSource();
  262. if (label.getText().trim().length() != 0) {
  263. selectedDay.setForeground(new Color(0, 0, 0));
  264. selectedDay.setOpaque(false);
  265. selectedDay = label;
  266. selectedDay.setForeground(new Color(255, 255, 255));
  267. selectedDay.setOpaque(true);
  268. }
  269. }
  270. }
  271. /**
  272. * 内部类,负责在日期面板的‘月’的处理。
  273. */
  274. private class MonthListener
  275. implements ActionListener {
  276. public void actionPerformed(ActionEvent e) {
  277. Calendar c = Calendar.getInstance();
  278. int y = ( (Integer) year.getValue()).intValue();
  279. int m = month.getSelectedIndex();
  280. int dayCount = daysOfMonth(y, m);
  281. int d = Integer.parseInt(selectedDay.getText().trim());
  282. if (d > dayCount) {
  283. d = dayCount;
  284. }
  285. c.set(y, m, d);
  286. processDays(c);
  287. }
  288. }
  289. /**
  290. * 内部类,负责在日期面板的‘年’的处理。
  291. */
  292. private class YearListener
  293. implements ChangeListener {
  294. public void stateChanged(ChangeEvent e) {
  295. Calendar c = Calendar.getInstance();
  296. int y = ( (Integer) year.getValue()).intValue();
  297. int m = month.getSelectedIndex();
  298. int dayCount = daysOfMonth(y, m);
  299. int d = Integer.parseInt(selectedDay.getText().trim());
  300. if (d > dayCount) {
  301. d = dayCount;
  302. }
  303. c.set(y, m, d);
  304. processDays(c);
  305. }
  306. }
  307. }