日期选择器——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 }
显示效果图如下:
作者:无言
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎微博互粉
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。