潘志宝
2024-12-10 29b971556c85da59d9f820dce13f8bce4d52056a
提交 | 用户 | 时间
149dd0 1 package com.iailab.netsdk.common;
H 2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Cursor;
6 import java.awt.Dimension;
7 import java.awt.FlowLayout;
8 import java.awt.Font;
9 import java.awt.GridLayout;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.ActionListener;
12 import java.awt.event.MouseEvent;
13 import java.awt.event.MouseListener;
14 import java.awt.event.WindowAdapter;
15 import java.awt.event.WindowEvent;
16 import java.text.ParseException;
17 import java.text.SimpleDateFormat;
18 import java.util.Calendar;
19 import java.util.Date;
20
21 import javax.swing.JButton;
22 import javax.swing.JDialog;
23 import javax.swing.JLabel;
24 import javax.swing.JPanel;
25 import javax.swing.JSpinner;
26 import javax.swing.SpinnerNumberModel;
27 import javax.swing.SwingConstants;
28 import javax.swing.UIManager;
29 import javax.swing.border.LineBorder;
30 import javax.swing.event.ChangeEvent;
31 import javax.swing.event.ChangeListener;
32
33 /**
34  * 时间选择器, 年月日
35  */
36 public class DateChooserJButtonEx extends JButton {
37     private static final long serialVersionUID = 1L;
38     
39     int startYear = 1980; // 默认【最小】显示年份
40     int lastYear = 2050; // 默认【最大】显示年份
41     
42     private DateChooser dateChooser = null;
43     private String preLabel = "";
44     private String originalText = null;
45     private SimpleDateFormat sdf = null;
46     
47     private JSpinner yearSpin;
48     private JSpinner monthSpin;
49     private JSpinner daySpin;
50     private JSpinner hourSpin;
51     private JSpinner minuteSpin;
52     private JSpinner secondSpin;
53     
54     public DateChooserJButtonEx() {
55         this(getNowDate());   
56         
57         try {
58             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
59         } catch (Exception e) {
60             e.printStackTrace();
61         } 
62     }
63
64     public DateChooserJButtonEx(String dateString) {
65         this();     
66         
67         setText(getDefaultDateFormat(), dateString);
68         //保存原始是日期时间
69         initOriginalText(dateString);
70     }
71
72     public DateChooserJButtonEx(SimpleDateFormat df, String dateString) {
73         this();
74         setText(df, dateString);
75
76         //记忆当前的日期格式化器
77         this.sdf = df;
78
79         //记忆原始日期时间
80         Date originalDate = null;
81         try {
82             originalDate = df.parse(dateString);
83         } catch (ParseException ex) {
84             originalDate = getNowDate();
85         }
86         initOriginalText(originalDate);
87     }
88
89     public DateChooserJButtonEx(Date date) {
90         this("", date);
91         //记忆原始日期时间
92         initOriginalText(date);
93     }
94
95     public DateChooserJButtonEx(String preLabel, Date date) {
96         if (preLabel != null) {
97             this.preLabel = preLabel;
98         }
99         setDate(date);
100         //记忆原始是日期时间
101         initOriginalText(date);
102
103         setBorder(null);
104         setCursor(new Cursor(Cursor.HAND_CURSOR));
105         super.addActionListener(new ActionListener() {
106
107             @Override
108             public void actionPerformed(ActionEvent e) {
109                 if (dateChooser == null) {
110                     dateChooser = new DateChooser();
111                 }
112
113                 dateChooser.showDateChooser();          
114             }
115         });
116     }
117     
118     public void setStartYear(int startYear) {
119         this.startYear = startYear;
120     }
121     
122     public void setLastYear(int lastYear) {
123         this.lastYear = lastYear;
124     }
125
126     private static Date getNowDate() {
127         return Calendar.getInstance().getTime();
128     }
129
130     private static SimpleDateFormat getDefaultDateFormat() {
131         return new SimpleDateFormat("yyyy-MM-dd");
132     }
133
134     /**
135      * 得到当前使用的日期格式化器
136      * @return 日期格式化器
137      */
138     public SimpleDateFormat getCurrentSimpleDateFormat(){
139         if(this.sdf != null){
140             return sdf;
141         }else{
142             return getDefaultDateFormat();
143         }
144     }
145
146
147     //保存原始是日期时间
148     private void initOriginalText(String dateString) {
149         this.originalText = dateString;
150     }
151
152     //保存原始是日期时间
153     private void initOriginalText(Date date) {
154         this.originalText = preLabel + getDefaultDateFormat().format(date);
155     }
156
157     /** 
158      * 得到当前记忆的原始日期时间
159      * @return 当前记忆的原始日期时间(未修改前的日期时间)
160      */
161     public String getOriginalText() {
162         return originalText;
163     }
164
165     // 覆盖父类的方法
166     @Override
167     public void setText(String s) {
168         Date date;
169         try {
170             date = getDefaultDateFormat().parse(s);
171         } catch (ParseException e) {
172             date = getNowDate();
173         }
174         setDate(date);
175         initOriginalText(date);
176     }
177
178     public void setText(SimpleDateFormat df, String s) {
179         Date date;
180         try {
181             date = df.parse(s);
182         } catch (ParseException e) {
183             date = getNowDate();
184         }
185         setDate(date);
186         initOriginalText(date);
187     }
188
189     public void setDate(Date date) {
190         super.setText(preLabel + getDefaultDateFormat().format(date));
191     }
192
193     public Date getDate() {
194         String dateString = getText().substring(preLabel.length());
195         try {
196             SimpleDateFormat currentSdf = getCurrentSimpleDateFormat();
197             return currentSdf.parse(dateString);
198         } catch (ParseException e) {
199             return getNowDate();
200         }
201     }
202
203     /**  
204      * 覆盖父类的方法使之无效
205      * @param listener 响应监听器
206      */
207     @Override
208     public void addActionListener(ActionListener listener) {
209     }
210
211     /**
212      * 内部类,主要是定义一个JPanel,然后把日历相关的所有内容填入本JPanel,
213      * 然后再创建一个JDialog,把本内部类定义的JPanel放入JDialog的内容区
214      */
215     private class DateChooser extends JPanel implements MouseListener, ChangeListener {
216         private static final long serialVersionUID = 1L;
217         
218         JLabel yearLabel;
219         JLabel monthLabel;
220         JLabel dayLabel;
221         
222         int width = 485; // 界面宽度
223         int height = 230; // 界面高度
224         Color backGroundColor = Color.gray; // 底色
225         // 月历表格配色----------------//
226         Color palletTableColor = Color.white; // 日历表底色
227         Color todayBackColor = Color.orange; // 今天背景色
228         Color weekFontColor = Color.blue; // 星期文字色
229         Color dateFontColor = Color.black; // 日期文字色
230         Color weekendFontColor = Color.red; // 周末文字色
231         // 控制条配色------------------//
232         Color controlLineColor = Color.pink; // 控制条底色
233         Color controlTextColor = Color.white; // 控制条标签文字色
234         
235         /** 点击DateChooserButton时弹出的对话框,日历内容在这个对话框内 */
236         JDialog dialog;
237         JLabel[][] daysLabels = new JLabel[6][7];
238
239         DateChooser() {
240             setLayout(new BorderLayout());
241             setBorder(new LineBorder(backGroundColor, 2));
242             setBackground(backGroundColor);
243
244             JPanel topYearAndMonth = createYearAndMonthPanal();
245             add(topYearAndMonth, BorderLayout.NORTH);
246             JPanel centerWeekAndDay = createWeekAndDayPanal();
247             add(centerWeekAndDay, BorderLayout.CENTER);
248             JPanel buttonBarPanel = createButtonBarPanel();
249             this.add(buttonBarPanel, BorderLayout.SOUTH);
250         }
251
252         private JPanel createYearAndMonthPanal() {
253             Calendar c = getCalendar();
254             int currentYear = c.get(Calendar.YEAR);
255             int currentMonth = c.get(Calendar.MONTH) + 1;
256             int currentDay = c.get(Calendar.DAY_OF_MONTH);
257
258             JPanel result = new JPanel();
259             result.setLayout(new FlowLayout());
260             result.setBackground(controlLineColor);
261
262             yearSpin = new JSpinner(new SpinnerNumberModel(currentYear, startYear, lastYear, 1));
263             yearSpin.setPreferredSize(new Dimension(48, 20));
264             yearSpin.setName("Year");
265             yearSpin.setEditor(new JSpinner.NumberEditor(yearSpin, "####"));
266             yearSpin.addChangeListener(this);
267             result.add(yearSpin);
268
269             yearLabel = new JLabel(Res.string().getYear());
270             yearLabel.setForeground(controlTextColor);
271             result.add(yearLabel);
272
273             monthSpin = new JSpinner(new SpinnerNumberModel(currentMonth, 1, 12, 1));
274             monthSpin.setPreferredSize(new Dimension(35, 20));
275             monthSpin.setName("Month");
276             monthSpin.addChangeListener(this);
277             result.add(monthSpin);
278
279             monthLabel = new JLabel(Res.string().getMonth());
280             monthLabel.setForeground(controlTextColor);
281             result.add(monthLabel);
282
283             //如果这里要能够选择,会要判断很多东西,比如每个月分别由多少日,以及闰年问题.所以,就干脆把Enable设为false
284             daySpin = new JSpinner(new SpinnerNumberModel(currentDay, 1, 31, 1));
285             daySpin.setPreferredSize(new Dimension(35, 20));
286             daySpin.setName("Day");
287             daySpin.addChangeListener(this);
288             daySpin.setEnabled(false);
289             result.add(daySpin);
290
291             dayLabel = new JLabel(Res.string().getDay());
292             dayLabel.setForeground(controlTextColor);
293             result.add(dayLabel);      
294
295             return result;
296         }
297
298         private JPanel createWeekAndDayPanal() {
299             Res.string().getWeek();
300             JPanel result = new JPanel();
301             // 设置固定字体,以免调用环境改变影响界面美观
302             result.setFont(new Font("宋体", Font.PLAIN, 12));
303             result.setLayout(new GridLayout(7, 7));
304             result.setBackground(Color.white);
305             JLabel cell;
306
307             for (int i = 0; i < 7; i++) {
308                 cell = new JLabel(Res.string().getWeek()[i]);
309                 cell.setHorizontalAlignment(JLabel.RIGHT);
310                 if (i == 0 || i == 6) {
311                     cell.setForeground(weekendFontColor);
312                 } else {
313                     cell.setForeground(weekFontColor);
314                 }
315                 result.add(cell);
316             }
317
318 //            int actionCommandId = 0;
319             for (int i = 0; i < 6; i++) {
320                 for (int j = 0; j < 7; j++) {
321                     JLabel numberLabel = new JLabel();
322                     numberLabel.setBorder(null);
323                     numberLabel.setHorizontalAlignment(SwingConstants.RIGHT);
324 //                    numberLabel.setActionCommand(String.valueOf(actionCommandId));
325                     numberLabel.addMouseListener(this);
326                     numberLabel.setBackground(palletTableColor);
327                     numberLabel.setForeground(dateFontColor);
328                     if (j == 0 || j == 6) {
329                         numberLabel.setForeground(weekendFontColor);
330                     } else {
331                         numberLabel.setForeground(dateFontColor);
332                     }
333                     daysLabels[i][j] = numberLabel;
334                     result.add(numberLabel);
335 //                    actionCommandId++;
336                 }
337             }
338
339             return result;
340         }
341
342         /** 得到DateChooserButton的当前text,本方法是为按钮事件匿名类准备的。 */
343         public String getTextOfDateChooserButton() {
344             return getText();
345         }
346
347         /** 恢复DateChooserButton的原始日期时间text,本方法是为按钮事件匿名类准备的。 */
348         public void restoreTheOriginalDate() {
349             String originalText = getOriginalText();
350             setText(originalText);
351         }
352
353         private JPanel createButtonBarPanel() {
354             JPanel panel = new JPanel();
355             panel.setLayout(new GridLayout(1, 2));
356
357             JButton ok = new JButton(Res.string().getConfirm());
358             ok.addActionListener(new ActionListener() {
359
360                 @Override
361                 public void actionPerformed(ActionEvent e) {
362                     //记忆原始日期时间
363                     initOriginalText(getTextOfDateChooserButton());
364                     //隐藏日历对话框
365                     dialog.setVisible(false);
366                 }
367             });
368             panel.add(ok);
369
370             JButton cancel = new JButton(Res.string().getCancel());
371             cancel.addActionListener(new ActionListener() {
372
373                 @Override
374                 public void actionPerformed(ActionEvent e) {
375                     //恢复原始的日期时间
376                     restoreTheOriginalDate();     
377                     //隐藏日历对话框
378                     dialog.setVisible(false);
379                 }
380             });
381
382             panel.add(cancel);
383             return panel;
384         }
385
386         private JDialog createDialog() {
387             JDialog result = new JDialog();
388             result.setTitle(Res.string().getDateChooser());
389             result.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
390             result.getContentPane().add(this, BorderLayout.CENTER);
391             result.pack();
392             result.setSize(width, height);
393             result.setModal(true);  
394             
395             result.addWindowListener(new WindowAdapter() {
396                 public void windowClosing(WindowEvent e) {
397                      //恢复原始的日期时间
398                     restoreTheOriginalDate();     
399                     //隐藏日历对话框
400                     dialog.setVisible(false);
401                 }
402             });
403             
404             return result;
405         }
406
407         void showDateChooser() {
408             if (dialog == null) {
409                 dialog = createDialog();
410             }
411             dialog.setLocationRelativeTo(null);
412             flushWeekAndDay();
413             dialog.setVisible(true);
414         }
415
416         private Calendar getCalendar() {
417             Calendar result = Calendar.getInstance();
418             result.setTime(getDate());
419             return result;
420         }
421
422         private int getSelectedYear() {
423             return ((Integer) yearSpin.getValue()).intValue();
424         }
425
426         private int getSelectedMonth() {
427             return ((Integer) monthSpin.getValue()).intValue();
428         }
429
430         private int getSelectedHour() {
431             return ((Integer) hourSpin.getValue()).intValue();
432         }
433
434         private int getSelectedMinite() {
435             return ((Integer) minuteSpin.getValue()).intValue();
436         }
437
438         private int getSelectedSecond() {
439             return ((Integer) secondSpin.getValue()).intValue();
440         }
441
442         private void dayColorUpdate(boolean isOldDay) {
443             Calendar c = getCalendar();
444             int day = c.get(Calendar.DAY_OF_MONTH);
445             c.set(Calendar.DAY_OF_MONTH, 1);
446             int actionCommandId = day - 2 + c.get(Calendar.DAY_OF_WEEK);
447             int i = actionCommandId / 7;
448             int j = actionCommandId % 7;
449             if (isOldDay) {
450                 daysLabels[i][j].setForeground(dateFontColor);
451             } else {
452                 daysLabels[i][j].setForeground(todayBackColor);
453             }
454         }
455
456         private void flushWeekAndDay() {     
457             Calendar c = getCalendar();
458             c.set(Calendar.DAY_OF_MONTH, 1);
459             int maxDayNo = c.getActualMaximum(Calendar.DAY_OF_MONTH);
460             int dayNo = 2 - c.get(Calendar.DAY_OF_WEEK);
461             for (int i = 0; i < 6; i++) {
462                 for (int j = 0; j < 7; j++) {
463                     String s = "";
464                     if (dayNo >= 1 && dayNo <= maxDayNo) {
465                         s = String.valueOf(dayNo);
466                     }
467                     daysLabels[i][j].setText(s);
468                     dayNo++;
469                 }
470             }
471
472             // 打开日历时,根据按钮的时间,设置日历的时间
473             String[] date1 = getText().split(" ")[0].split("-");
474
475             yearSpin.setValue(new Integer(date1[0]));
476             monthSpin.setValue(new Integer(date1[1]));
477             daySpin.setValue(new Integer(date1[2]));
478
479             // 重置日历天的数字颜色
480             for(int i = 0; i < 6; i++) {
481                 for(int j = 0; j < 7; j++) {
482                     if(!daysLabels[i][j].getText().equals("")) {
483                         daysLabels[i][j].setForeground(Color.BLACK);
484                     }
485                 }
486             }
487             
488             // 重置日历星期六、星期日的数字颜色
489             for(int i = 0; i < 6; i++) {
490                 if(!daysLabels[i][0].getText().equals("")) {
491                     daysLabels[i][0].setForeground(weekendFontColor);
492                 }
493                 if(!daysLabels[i][6].getText().equals("")) {
494                     daysLabels[i][6].setForeground(weekendFontColor);
495                 }
496             }
497             
498             // 设置当天的数字颜色
499             for(int i = 0; i < 6; i++) {
500                 for(int j = 0; j < 7; j++) {
501                     if(daysLabels[i][j].getText().equals(date1[2])) {
502                         daysLabels[i][j].setForeground(todayBackColor);
503                     }
504                 }
505             }
506
507             dayColorUpdate(false);
508         }
509
510         /**
511          * 选择日期时的响应事件
512          */
513         @Override
514         public void stateChanged(ChangeEvent e) {
515             JSpinner source = (JSpinner) e.getSource();
516             Calendar c = getCalendar();
517             if (source.getName().equals("Hour")) {
518                 c.set(Calendar.HOUR_OF_DAY, getSelectedHour());
519                 setDate(c.getTime());
520                 return;
521             }
522             if (source.getName().equals("Minute")) {
523                 c.set(Calendar.MINUTE, getSelectedMinite());
524                 setDate(c.getTime());
525                 return;
526             }
527             if (source.getName().equals("Second")) {
528                 c.set(Calendar.SECOND, getSelectedSecond());
529                 setDate(c.getTime());
530                 return;
531             }
532
533             dayColorUpdate(true);
534
535             if (source.getName().equals("Year")) {
536                 c.set(Calendar.YEAR, getSelectedYear());
537             } else if (source.getName().equals("Month")) {
538                 c.set(Calendar.MONTH, getSelectedMonth() - 1);
539             }
540             setDate(c.getTime());
541             flushWeekAndDay();
542         }
543
544         /**
545          * 选择日期时的响应事件
546          */
547         @Override
548         public void mouseClicked(MouseEvent e) {
549             JLabel source = (JLabel) e.getSource();
550             if (source.getText().length() == 0) {
551                 return;
552             }
553             dayColorUpdate(true);
554             source.setForeground(todayBackColor);
555             int newDay = Integer.parseInt(source.getText());
556             Calendar c = getCalendar();
557             c.set(Calendar.DAY_OF_MONTH, newDay);
558             setDate(c.getTime());
559             //把daySpin中的值也变了
560             daySpin.setValue(Integer.valueOf(newDay));
561         }
562
563         @Override
564         public void mouseEntered(MouseEvent arg0) {
565             // TODO Auto-generated method stub
566             
567         }
568
569         @Override
570         public void mouseExited(MouseEvent arg0) {
571             // TODO Auto-generated method stub
572             
573         }
574
575         @Override
576         public void mousePressed(MouseEvent arg0) {
577             // TODO Auto-generated method stub
578             
579         }
580
581         @Override
582         public void mouseReleased(MouseEvent arg0) {
583             // TODO Auto-generated method stub
584             
585         }
586     }
587 }