日期选择器——java

转载:http://zgdeng.iteye.com/blog/1405650

代码如下:

  1 import java.awt.BasicStroke;
  2 import java.awt.BorderLayout;
  3 import java.awt.Color;
  4 import java.awt.Component;
  5 import java.awt.Cursor;
  6 import java.awt.Dimension;
  7 import java.awt.Font;
  8 import java.awt.Graphics;
  9 import java.awt.Graphics2D;
 10 import java.awt.GridLayout;
 11 import java.awt.Point;
 12 import java.awt.Polygon;
 13 import java.awt.Stroke;
 14 import java.awt.Toolkit;
 15 import java.awt.event.FocusEvent;
 16 import java.awt.event.FocusListener;
 17 import java.awt.event.MouseAdapter;
 18 import java.awt.event.MouseEvent;
 19 import java.awt.event.MouseListener;
 20 import java.awt.event.MouseMotionListener;
 21 import java.text.SimpleDateFormat;
 22 import java.util.ArrayList;
 23 import java.util.Calendar;
 24 import java.util.Comparator;
 25 import java.util.Date;
 26 import java.util.List;
 27 
 28 import javax.swing.BorderFactory;
 29 import javax.swing.JComponent;
 30 import javax.swing.JFrame;
 31 import javax.swing.JLabel;
 32 import javax.swing.JPanel;
 33 import javax.swing.JTextField;
 34 import javax.swing.Popup;
 35 import javax.swing.PopupFactory;
 36 import javax.swing.SwingUtilities;
 37 import javax.swing.event.AncestorEvent;
 38 import javax.swing.event.AncestorListener;
 39 
 40 /**
 41  * 日期选择器,可以指定日期的显示格式
 42  */
 43 public class DateChooser extends JPanel {
 44 
 45     private static final long serialVersionUID = 4529266044762990227L;
 46 
 47     private Date initDate;
 48     private Calendar now = Calendar.getInstance();
 49     private Calendar select;
 50     private JPanel monthPanel;// 月历
 51     private JP1 jp1;// 四块面板,组成
 52     private JP2 jp2;
 53     private JP3 jp3;
 54     private JP4 jp4;
 55     private Font font = new Font("宋体", Font.PLAIN, 12);
 56     private final LabelManager lm = new LabelManager();
 57     private SimpleDateFormat sdf;
 58     private boolean isShow = false;
 59     private Popup pop;
 60 
 61     private JComponent showDate;
 62 
 63     public static DateChooser getInstance() {
 64         return new DateChooser();
 65     }
 66 
 67     public static DateChooser getInstance(Date date) {
 68         return new DateChooser(date);
 69     }
 70 
 71     public static DateChooser getInstance(String format) {
 72         return new DateChooser(format);
 73     }
 74 
 75     public static DateChooser getInstance(Date date, String format) {
 76         return new DateChooser(date, format);
 77     }
 78 
 79     /**
 80      * Creates a new instance of DateChooser
 81      */
 82     private DateChooser() {
 83         this(new Date());
 84     }
 85 
 86     private DateChooser(Date date) {
 87         this(date, "yyyy年MM月dd日");
 88     }
 89 
 90     private DateChooser(String format) {
 91         this(new Date(), format);
 92     }
 93 
 94     private DateChooser(Date date, String format) {
 95         initDate = date;
 96         sdf = new SimpleDateFormat(format);
 97         select = Calendar.getInstance();
 98         select.setTime(initDate);
 99         initPanel();
100     }
101 
102     /**
103      * 是否允许用户选择
104      */
105     public void setEnabled(boolean b) {
106         super.setEnabled(b);
107         showDate.setEnabled(b);
108     }
109 
110     /**
111      * 得到当前选择框的日期
112      */
113     public Date getDate() {
114         return select.getTime();
115     }
116 
117     public String getStrDate() {
118         return sdf.format(select.getTime());
119     }
120 
121     public String getStrDate(String format) {
122         sdf = new SimpleDateFormat(format);
123         return sdf.format(select.getTime());
124     }
125 
126     // 根据初始化的日期,初始化面板
127     private void initPanel() {
128         monthPanel = new JPanel(new BorderLayout());
129         monthPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
130         JPanel up = new JPanel(new BorderLayout());
131         up.add(jp1 = new JP1(), BorderLayout.NORTH);
132         up.add(jp2 = new JP2(), BorderLayout.CENTER);
133         monthPanel.add(jp3 = new JP3(), BorderLayout.CENTER);
134         monthPanel.add(up, BorderLayout.NORTH);
135         monthPanel.add(jp4 = new JP4(), BorderLayout.SOUTH);
136         this.addAncestorListener(new AncestorListener() {
137             public void ancestorAdded(AncestorEvent event) {
138 
139             }
140 
141             public void ancestorRemoved(AncestorEvent event) {
142 
143             }
144 
145             // 只要祖先组件一移动,马上就让popup消失
146             public void ancestorMoved(AncestorEvent event) {
147                 hidePanel();
148             }
149         });
150     }
151 
152     public void register(final JComponent showDate) {
153         this.showDate = showDate;
154 
155         showDate.setRequestFocusEnabled(true);
156         showDate.addMouseListener(new MouseAdapter() {
157             public void mousePressed(MouseEvent me) {
158                 showDate.requestFocusInWindow();
159             }
160         });
161         this.setBackground(Color.WHITE);
162         this.add(showDate, BorderLayout.CENTER);
163         this.setPreferredSize(new Dimension(90, 25));
164         this.setBorder(BorderFactory.createLineBorder(Color.GRAY));
165         showDate.addMouseListener(new MouseAdapter() {
166             public void mouseEntered(MouseEvent me) {
167                 if (showDate.isEnabled()) {
168                     showDate.setCursor(new Cursor(Cursor.HAND_CURSOR));
169                     showDate.setForeground(Color.RED);
170                 }
171             }
172 
173             public void mouseExited(MouseEvent me) {
174                 if (showDate.isEnabled()) {
175                     showDate.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
176                     showDate.setForeground(Color.BLACK);
177                 }
178             }
179 
180             public void mousePressed(MouseEvent me) {
181                 if (showDate.isEnabled()) {
182                     showDate.setForeground(Color.CYAN);
183                     if (isShow) {
184                         hidePanel();
185                     } else {
186                         showPanel(showDate);
187                     }
188                 }
189             }
190 
191             public void mouseReleased(MouseEvent me) {
192                 if (showDate.isEnabled()) {
193                     showDate.setForeground(Color.BLACK);
194                 }
195             }
196         });
197         showDate.addFocusListener(new FocusListener() {
198             public void focusLost(FocusEvent e) {
199                 hidePanel();
200             }
201 
202             public void focusGained(FocusEvent e) {
203 
204             }
205         });
206     }
207 
208     // 根据新的日期刷新
209     private void refresh() {
210         jp1.updateDate();
211         jp2.updateDate();
212         jp3.updateDate();
213         jp4.updateDate();
214         SwingUtilities.updateComponentTreeUI(this);
215     }
216 
217     // 提交日期
218     private void commit() {
219         // TODO add other components here
220         if (showDate instanceof JTextField) {
221             ((JTextField) showDate).setText(sdf.format(select.getTime()));
222         } else if (showDate instanceof JLabel) {
223             ((JLabel) showDate).setText(sdf.format(select.getTime()));
224         }
225 
226         hidePanel();
227     }
228 
229     // 隐藏日期选择面板
230     private void hidePanel() {
231         if (pop != null) {
232             isShow = false;
233             pop.hide();
234             pop = null;
235         }
236     }
237 
238     // 显示日期选择面板
239     private void showPanel(Component owner) {
240         if (pop != null) {
241             pop.hide();
242         }
243         Point show = new Point(0, showDate.getHeight());
244         SwingUtilities.convertPointToScreen(show, showDate);
245         Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
246         int x = show.x;
247         int y = show.y;
248         if (x < 0) {
249             x = 0;
250         }
251         if (x > size.width - 295) {
252             x = size.width - 295;
253         }
254         if (y < size.height - 170) {
255         } else {
256             y -= 188;
257         }
258         pop = PopupFactory.getSharedInstance()
259                 .getPopup(owner, monthPanel, x, y);
260         pop.show();
261         isShow = true;
262     }
263 
264     /**
265      * 最上面的面板用来显示月份的增减
266      */
267     private class JP1 extends JPanel {
268         private static final long serialVersionUID = -5638853772805561174L;
269         JLabel yearleft, yearright, monthleft, monthright, center,
270                 centercontainer;
271 
272         public JP1() {
273             super(new BorderLayout());
274             this.setBackground(new Color(160, 185, 215));
275             initJP1();
276         }
277 
278         private void initJP1() {
279             yearleft = new JLabel("  <<", JLabel.CENTER);
280             yearleft.setToolTipText("上一年");
281             yearright = new JLabel(">>  ", JLabel.CENTER);
282             yearright.setToolTipText("下一年");
283             yearleft.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
284             yearright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
285 
286             monthleft = new JLabel("  <", JLabel.RIGHT);
287             monthleft.setToolTipText("上一月");
288             monthright = new JLabel(">  ", JLabel.LEFT);
289             monthright.setToolTipText("下一月");
290             monthleft.setBorder(BorderFactory.createEmptyBorder(2, 30, 0, 0));
291             monthright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 30));
292 
293             centercontainer = new JLabel("", JLabel.CENTER);
294             centercontainer.setLayout(new BorderLayout());
295             center = new JLabel("", JLabel.CENTER);
296 
297             centercontainer.add(monthleft, BorderLayout.WEST);
298             centercontainer.add(center, BorderLayout.CENTER);
299             centercontainer.add(monthright, BorderLayout.EAST);
300 
301             this.add(yearleft, BorderLayout.WEST);
302             this.add(centercontainer, BorderLayout.CENTER);
303             this.add(yearright, BorderLayout.EAST);
304             this.setPreferredSize(new Dimension(295, 25));
305 
306             updateDate();
307 
308             yearleft.addMouseListener(new MouseAdapter() {
309                 public void mouseEntered(MouseEvent me) {
310                     yearleft.setCursor(new Cursor(Cursor.HAND_CURSOR));
311                     yearleft.setForeground(Color.RED);
312                 }
313 
314                 public void mouseExited(MouseEvent me) {
315                     yearleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
316                     yearleft.setForeground(Color.BLACK);
317                 }
318 
319                 public void mousePressed(MouseEvent me) {
320                     select.add(Calendar.YEAR, -1);
321                     yearleft.setForeground(Color.WHITE);
322                     refresh();
323                 }
324 
325                 public void mouseReleased(MouseEvent me) {
326                     yearleft.setForeground(Color.BLACK);
327                 }
328             });
329             yearright.addMouseListener(new MouseAdapter() {
330                 public void mouseEntered(MouseEvent me) {
331                     yearright.setCursor(new Cursor(Cursor.HAND_CURSOR));
332                     yearright.setForeground(Color.RED);
333                 }
334 
335                 public void mouseExited(MouseEvent me) {
336                     yearright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
337                     yearright.setForeground(Color.BLACK);
338                 }
339 
340                 public void mousePressed(MouseEvent me) {
341                     select.add(Calendar.YEAR, 1);
342                     yearright.setForeground(Color.WHITE);
343                     refresh();
344                 }
345 
346                 public void mouseReleased(MouseEvent me) {
347                     yearright.setForeground(Color.BLACK);
348                 }
349             });
350             monthleft.addMouseListener(new MouseAdapter() {
351                 public void mouseEntered(MouseEvent me) {
352                     monthleft.setCursor(new Cursor(Cursor.HAND_CURSOR));
353                     monthleft.setForeground(Color.RED);
354                 }
355 
356                 public void mouseExited(MouseEvent me) {
357                     monthleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
358                     monthleft.setForeground(Color.BLACK);
359                 }
360 
361                 public void mousePressed(MouseEvent me) {
362                     select.add(Calendar.MONTH, -1);
363                     monthleft.setForeground(Color.WHITE);
364                     refresh();
365                 }
366 
367                 public void mouseReleased(MouseEvent me) {
368                     monthleft.setForeground(Color.BLACK);
369                 }
370             });
371             monthright.addMouseListener(new MouseAdapter() {
372                 public void mouseEntered(MouseEvent me) {
373                     monthright.setCursor(new Cursor(Cursor.HAND_CURSOR));
374                     monthright.setForeground(Color.RED);
375                 }
376 
377                 public void mouseExited(MouseEvent me) {
378                     monthright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
379                     monthright.setForeground(Color.BLACK);
380                 }
381 
382                 public void mousePressed(MouseEvent me) {
383                     select.add(Calendar.MONTH, 1);
384                     monthright.setForeground(Color.WHITE);
385                     refresh();
386                 }
387 
388                 public void mouseReleased(MouseEvent me) {
389                     monthright.setForeground(Color.BLACK);
390                 }
391             });
392         }
393 
394         private void updateDate() {
395             center.setText(select.get(Calendar.YEAR) + "年"
396                     + (select.get(Calendar.MONTH) + 1) + "月");
397         }
398     }
399 
400     private class JP2 extends JPanel {
401         private static final long serialVersionUID = -8176264838786175724L;
402 
403         public JP2() {
404             this.setPreferredSize(new Dimension(295, 20));
405         }
406 
407         protected void paintComponent(Graphics g) {
408             g.setFont(font);
409             g.drawString("星期日 星期一 星期二 星期三 星期四 星期五 星期六", 5, 10);
410             g.drawLine(0, 15, getWidth(), 15);
411         }
412 
413         private void updateDate() {
414 
415         }
416     }
417 
418     private class JP3 extends JPanel {
419         private static final long serialVersionUID = 43157272447522985L;
420 
421         public JP3() {
422             super(new GridLayout(6, 7));
423             this.setPreferredSize(new Dimension(295, 100));
424             initJP3();
425         }
426 
427         private void initJP3() {
428             updateDate();
429         }
430 
431         public void updateDate() {
432             this.removeAll();
433             lm.clear();
434             Date temp = select.getTime();
435             Calendar select = Calendar.getInstance();
436             select.setTime(temp);
437             select.set(Calendar.DAY_OF_MONTH, 1);
438             int index = select.get(Calendar.DAY_OF_WEEK);
439             int sum = (index == 1 ? 8 : index);
440             select.add(Calendar.DAY_OF_MONTH, 0 - sum);
441             for (int i = 0; i < 42; i++) {
442                 select.add(Calendar.DAY_OF_MONTH, 1);
443                 lm.addLabel(new MyLabel(select.get(Calendar.YEAR), select
444                         .get(Calendar.MONTH), select.get(Calendar.DAY_OF_MONTH)));
445             }
446             for (MyLabel my : lm.getLabels()) {
447                 this.add(my);
448             }
449             select.setTime(temp);
450         }
451     }
452 
453     private class MyLabel extends JLabel implements Comparator<MyLabel>,
454             MouseListener, MouseMotionListener {
455         private static final long serialVersionUID = 3668734399227577214L;
456         private int year, month, day;
457         private boolean isSelected;
458 
459         public MyLabel(int year, int month, int day) {
460             super("" + day, JLabel.CENTER);
461             this.year = year;
462             this.day = day;
463             this.month = month;
464             this.addMouseListener(this);
465             this.addMouseMotionListener(this);
466             this.setFont(font);
467             if (month == select.get(Calendar.MONTH)) {
468                 this.setForeground(Color.BLACK);
469             } else {
470                 this.setForeground(Color.LIGHT_GRAY);
471             }
472             if (day == select.get(Calendar.DAY_OF_MONTH)) {
473                 this.setBackground(new Color(160, 185, 215));
474             } else {
475                 this.setBackground(Color.WHITE);
476             }
477         }
478 
479         public boolean getIsSelected() {
480             return isSelected;
481         }
482 
483         public void setSelected(boolean b, boolean isDrag) {
484             isSelected = b;
485             if (b && !isDrag) {
486                 int temp = select.get(Calendar.MONTH);
487                 select.set(year, month, day);
488                 if (temp == month) {
489                     SwingUtilities.updateComponentTreeUI(jp3);
490                 } else {
491                     refresh();
492                 }
493             }
494             this.repaint();
495         }
496 
497         protected void paintComponent(Graphics g) {
498             if (day == select.get(Calendar.DAY_OF_MONTH)
499                     && month == select.get(Calendar.MONTH)) {
500                 // 如果当前日期是选择日期,则高亮显示
501                 g.setColor(new Color(160, 185, 215));
502                 g.fillRect(0, 0, getWidth(), getHeight());
503             }
504             if (year == now.get(Calendar.YEAR)
505                     && month == now.get(Calendar.MONTH)
506                     && day == now.get(Calendar.DAY_OF_MONTH)) {
507                 // 如果日期和当前日期一样,则用红框
508                 Graphics2D gd = (Graphics2D) g;
509                 gd.setColor(Color.RED);
510                 Polygon p = new Polygon();
511                 p.addPoint(0, 0);
512                 p.addPoint(getWidth() - 1, 0);
513                 p.addPoint(getWidth() - 1, getHeight() - 1);
514                 p.addPoint(0, getHeight() - 1);
515                 gd.drawPolygon(p);
516             }
517             if (isSelected) {// 如果被选中了就画出一个虚线框出来
518                 Stroke s = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE,
519                         BasicStroke.JOIN_BEVEL, 1.0f,
520                         new float[] { 2.0f, 2.0f }, 1.0f);
521                 Graphics2D gd = (Graphics2D) g;
522                 gd.setStroke(s);
523                 gd.setColor(Color.BLACK);
524                 Polygon p = new Polygon();
525                 p.addPoint(0, 0);
526                 p.addPoint(getWidth() - 1, 0);
527                 p.addPoint(getWidth() - 1, getHeight() - 1);
528                 p.addPoint(0, getHeight() - 1);
529                 gd.drawPolygon(p);
530             }
531             super.paintComponent(g);
532         }
533 
534         public boolean contains(Point p) {
535             return this.getBounds().contains(p);
536         }
537 
538         private void update() {
539             repaint();
540         }
541 
542         public void mouseClicked(MouseEvent e) {
543         }
544 
545         public void mousePressed(MouseEvent e) {
546             isSelected = true;
547             update();
548         }
549 
550         public void mouseReleased(MouseEvent e) {
551             Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3);
552             lm.setSelect(p, false);
553             commit();
554         }
555 
556         public void mouseEntered(MouseEvent e) {
557         }
558 
559         public void mouseExited(MouseEvent e) {
560         }
561 
562         public void mouseDragged(MouseEvent e) {
563             Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3);
564             lm.setSelect(p, true);
565         }
566 
567         public void mouseMoved(MouseEvent e) {
568         }
569 
570         public int compare(MyLabel o1, MyLabel o2) {
571             Calendar c1 = Calendar.getInstance();
572             c1.set(o1.year, o2.month, o1.day);
573             Calendar c2 = Calendar.getInstance();
574             c2.set(o2.year, o2.month, o2.day);
575             return c1.compareTo(c2);
576         }
577     }
578 
579     private class LabelManager {
580         private List<MyLabel> list;
581 
582         public LabelManager() {
583             list = new ArrayList<MyLabel>();
584         }
585 
586         public List<MyLabel> getLabels() {
587             return list;
588         }
589 
590         public void addLabel(MyLabel my) {
591             list.add(my);
592         }
593 
594         public void clear() {
595             list.clear();
596         }
597 
598         @SuppressWarnings("unused")
599         public void setSelect(MyLabel my, boolean b) {
600             for (MyLabel m : list) {
601                 if (m.equals(my)) {
602                     m.setSelected(true, b);
603                 } else {
604                     m.setSelected(false, b);
605                 }
606             }
607         }
608 
609         public void setSelect(Point p, boolean b) {
610             // 如果是拖动,则要优化一下,以提高效率
611             if (b) {
612                 // 表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和
613                 // 将要显示的标签找到了就可以了
614                 boolean findPrevious = false, findNext = false;
615                 for (MyLabel m : list) {
616                     if (m.contains(p)) {
617                         findNext = true;
618                         if (m.getIsSelected()) {
619                             findPrevious = true;
620                         } else {
621                             m.setSelected(true, b);
622                         }
623                     } else if (m.getIsSelected()) {
624                         findPrevious = true;
625                         m.setSelected(false, b);
626                     }
627                     if (findPrevious && findNext) {
628                         return;
629                     }
630                 }
631             } else {
632                 MyLabel temp = null;
633                 for (MyLabel m : list) {
634                     if (m.contains(p)) {
635                         temp = m;
636                     } else if (m.getIsSelected()) {
637                         m.setSelected(false, b);
638                     }
639                 }
640                 if (temp != null) {
641                     temp.setSelected(true, b);
642                 }
643             }
644         }
645 
646     }
647 
648     private class JP4 extends JPanel {
649         private static final long serialVersionUID = -6391305687575714469L;
650 
651         public JP4() {
652             super(new BorderLayout());
653             this.setPreferredSize(new Dimension(295, 20));
654             this.setBackground(new Color(160, 185, 215));
655             SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
656             final JLabel jl = new JLabel("今天: " + sdf.format(new Date()));
657             jl.setToolTipText("点击选择今天日期");
658             this.add(jl, BorderLayout.CENTER);
659             jl.addMouseListener(new MouseAdapter() {
660                 public void mouseEntered(MouseEvent me) {
661                     jl.setCursor(new Cursor(Cursor.HAND_CURSOR));
662                     jl.setForeground(Color.RED);
663                 }
664 
665                 public void mouseExited(MouseEvent me) {
666                     jl.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
667                     jl.setForeground(Color.BLACK);
668                 }
669 
670                 public void mousePressed(MouseEvent me) {
671                     jl.setForeground(Color.WHITE);
672                     select.setTime(new Date());
673                     refresh();
674                     commit();
675                 }
676 
677                 public void mouseReleased(MouseEvent me) {
678                     jl.setForeground(Color.BLACK);
679                 }
680             });
681         }
682 
683         private void updateDate() {
684 
685         }
686     }
687 
688     public static void main(String[] args) {
689         DateChooser dateChooser1 = DateChooser.getInstance("yyyy-MM-dd");
690         DateChooser dateChooser2 = DateChooser.getInstance("yyyy-MM-dd");
691         JTextField showDate1 = new JTextField("单击选择日期");
692         JLabel showDate2 = new JLabel("单击选择日期");
693 
694         dateChooser1.register(showDate1);
695         dateChooser2.register(showDate2);
696 
697         JFrame jf = new JFrame("测试日期选择器");
698         jf.add(showDate1, BorderLayout.NORTH);
699         jf.add(showDate2, BorderLayout.SOUTH);
700         jf.pack();
701         jf.setLocationRelativeTo(null);
702         jf.setVisible(true);
703         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
704     }
705 }

显示效果图如下:

 

posted @ 2015-04-01 11:04  HuijunZhang  阅读(6567)  评论(0编辑  收藏  举报
中国