添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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; 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; 40 /** 41 * 日期选择器,可以指定日期的显示格式 42 */ 43 public class DateChooser extends JPanel { 45 private static final long serialVersionUID = 4529266044762990227L ; 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; 61 private JComponent showDate; 63 public static DateChooser getInstance() { 64 return new DateChooser(); 65 } 67 public static DateChooser getInstance(Date date) { 68 return new DateChooser(date); 69 } 71 public static DateChooser getInstance(String format) { 72 return new DateChooser(format); 73 } 75 public static DateChooser getInstance(Date date, String format) { 76 return new DateChooser(date, format); 77 } 79 /** 80 * Creates a new instance of DateChooser 81 */ 82 private DateChooser() { 83 this ( new Date()); 84 } 86 private DateChooser(Date date) { 87 this (date, "yyyy年MM月dd日" ); 88 } 90 private DateChooser(String format) { 91 this ( new Date(), format); 92 } 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 } 102 /** 103 * 是否允许用户选择 104 */ 105 public void setEnabled( boolean b) { 106 super .setEnabled(b); 107 showDate.setEnabled(b); 108 } 110 /** 111 * 得到当前选择框的日期 112 */ 113 public Date getDate() { 114 return select.getTime(); 115 } 117 public String getStrDate() { 118 return sdf.format(select.getTime()); 119 } 121 public String getStrDate(String format) { 122 sdf = new SimpleDateFormat(format); 123 return sdf.format(select.getTime()); 124 } 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) { 139 } 141 public void ancestorRemoved(AncestorEvent event) { 143 } 145 // 只要祖先组件一移动,马上就让popup消失 146 public void ancestorMoved(AncestorEvent event) { 147 hidePanel(); 148 } 149 }); 150 } 152 public void register( final JComponent showDate) { 153 this .showDate = showDate; 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 } 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 } 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 } 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 } 202 public void focusGained(FocusEvent e) { 204 } 205 }); 206 } 208 // 根据新的日期刷新 209 private void refresh() { 210 jp1.updateDate(); 211 jp2.updateDate(); 212 jp3.updateDate(); 213 jp4.updateDate(); 214 SwingUtilities.updateComponentTreeUI( this ); 215 } 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 } 226 hidePanel(); 227 } 229 // 隐藏日期选择面板 230 private void hidePanel() { 231 if (pop != null ) { 232 isShow = false ; 233 pop.hide(); 234 pop = null ; 235 } 236 } 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 } 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; 272 public JP1() { 273 super ( new BorderLayout()); 274 this .setBackground( new Color(160, 185, 215 )); 275 initJP1(); 276 } 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 )); 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 )); 293 centercontainer = new JLabel("" , JLabel.CENTER); 294 centercontainer.setLayout( new BorderLayout()); 295 center = new JLabel("" , JLabel.CENTER); 297 centercontainer.add(monthleft, BorderLayout.WEST); 298 centercontainer.add(center, BorderLayout.CENTER); 299 centercontainer.add(monthright, BorderLayout.EAST); 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 )); 306 updateDate(); 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 } 314 public void mouseExited(MouseEvent me) { 315 yearleft.setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); 316 yearleft.setForeground(Color.BLACK); 317 } 319 public void mousePressed(MouseEvent me) { 320 select.add(Calendar.YEAR, -1 ); 321 yearleft.setForeground(Color.WHITE); 322 refresh(); 323 } 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 } 335 public void mouseExited(MouseEvent me) { 336 yearright.setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); 337 yearright.setForeground(Color.BLACK); 338 } 340 public void mousePressed(MouseEvent me) { 341 select.add(Calendar.YEAR, 1 ); 342 yearright.setForeground(Color.WHITE); 343 refresh(); 344 } 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 } 356 public void mouseExited(MouseEvent me) { 357 monthleft.setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); 358 monthleft.setForeground(Color.BLACK); 359 } 361 public void mousePressed(MouseEvent me) { 362 select.add(Calendar.MONTH, -1 ); 363 monthleft.setForeground(Color.WHITE); 364 refresh(); 365 } 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 } 377 public void mouseExited(MouseEvent me) { 378 monthright.setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); 379 monthright.setForeground(Color.BLACK); 380 } 382 public void mousePressed(MouseEvent me) { 383 select.add(Calendar.MONTH, 1 ); 384 monthright.setForeground(Color.WHITE); 385 refresh(); 386 } 388 public void mouseReleased(MouseEvent me) { 389 monthright.setForeground(Color.BLACK); 390 } 391 }); 392 } 394 private void updateDate() { 395 center.setText(select.get(Calendar.YEAR) + "年" 396 + (select.get(Calendar.MONTH) + 1) + "月" ); 397 } 398 } 400 private class JP2 extends JPanel { 401 private static final long serialVersionUID = -8176264838786175724L ; 403 public JP2() { 404 this .setPreferredSize( new Dimension(295, 20 )); 405 } 407 protected void paintComponent(Graphics g) { 408 g.setFont(font); 409 g.drawString("星期日 星期一 星期二 星期三 星期四 星期五 星期六", 5, 10 ); 410 g.drawLine(0, 15, getWidth(), 15 ); 411 } 413 private void updateDate() { 415 } 416 } 418 private class JP3 extends JPanel { 419 private static final long serialVersionUID = 43157272447522985L ; 421 public JP3() { 422 super ( new GridLayout(6, 7 )); 423 this .setPreferredSize( new Dimension(295, 100 )); 424 initJP3(); 425 } 427 private void initJP3() { 428 updateDate(); 429 } 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 } 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; 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 } 479 public boolean getIsSelected() { 480 return isSelected; 481 } 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 } 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 } 534 public boolean contains(Point p) { 535 return this .getBounds().contains(p); 536 } 538 private void update() { 539 repaint(); 540 } 542 public void mouseClicked(MouseEvent e) { 543 } 545 public void mousePressed(MouseEvent e) { 546 isSelected = true ; 547 update(); 548 } 550 public void mouseReleased(MouseEvent e) { 551 Point p = SwingUtilities.convertPoint( this , e.getPoint(), jp3); 552 lm.setSelect(p, false ); 553 commit(); 554 } 556 public void mouseEntered(MouseEvent e) { 557 } 559 public void mouseExited(MouseEvent e) { 560 } 562 public void mouseDragged(MouseEvent e) { 563 Point p = SwingUtilities.convertPoint( this , e.getPoint(), jp3); 564 lm.setSelect(p, true ); 565 } 567 public void mouseMoved(MouseEvent e) { 568 } 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 } 579 private class LabelManager { 580 private List<MyLabel> list; 582 public LabelManager() { 583 list = new ArrayList<MyLabel> (); 584 } 586 public List<MyLabel> getLabels() { 587 return list; 588 } 590 public void addLabel(MyLabel my) { 591 list.add(my); 592 } 594 public void clear() { 595 list.clear(); 596 } 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 } 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 } 646 } 648 private class JP4 extends JPanel { 649 private static final long serialVersionUID = -6391305687575714469L ; 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 } 665 public void mouseExited(MouseEvent me) { 666 jl.setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); 667 jl.setForeground(Color.BLACK); 668 } 670 public void mousePressed(MouseEvent me) { 671 jl.setForeground(Color.WHITE); 672 select.setTime( new Date()); 673 refresh(); 674 commit(); 675 } 677 public void mouseReleased(MouseEvent me) { 678 jl.setForeground(Color.BLACK); 679 } 680 }); 681 } 683 private void updateDate() { 685 } 686 } 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("单击选择日期" ); 694 dateChooser1.register(showDate1); 695 dateChooser2.register(showDate2); 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 }

显示效果图如下: