1 package com.ryd.stocktrader.client.util; 2 3 import java.awt.Color; 4 import java.awt.GridLayout; 5 import java.awt.Label; 6 import java.awt.TextField; 7 import java.awt.event.ActionEvent; 8 import java.awt.event.ActionListener; 9 import java.awt.event.MouseAdapter; 10 import java.awt.event.MouseEvent; 11 import java.text.ParseException; 12 import java.text.SimpleDateFormat; 13 import java.util.Calendar; 14 import java.util.Date; 15 import java.util.GregorianCalendar; 16 17 import javax.swing.BorderFactory; 18 import javax.swing.JButton; 19 import javax.swing.JComponent; 20 import javax.swing.JLabel; 21 import javax.swing.JPanel; 22 import javax.swing.JTextField; 23 import javax.swing.SwingConstants; 24 25 public class CalendarPanel extends JPanel { 26 27 /** 28 * 29 */ 30 private static final long serialVersionUID = 1L; 31 32 private JLabel btn_lastYear = null; 33 private JLabel btn_nextYear = null; 34 private JLabel btn_lastMonth = null; 35 private JLabel btn_nextMonth = null; 36 private JLabel lb_datetime = null; 37 private JPanel panel_maincalenderpanel = null; 38 private JLabel lblNewLabel = null; 39 private JLabel label = null; 40 private JLabel label_1 = null; 41 private JLabel label_2 = null; 42 private JLabel label_3 = null; 43 private JLabel label_4 = null; 44 private JLabel label_5 = null; 45 private JLabel btn_close = null; 46 private JButton btn_today = null; 47 private JButton btn_cancel = null; 48 private Object component = null; //日历控件的载体组件,如TextField 49 private String returnDateStr = null; //保存选中的日期 50 private CallBack callBack = null; 51 52 private String patern = "yyyy-MM-dd"; //日期格式 53 private SimpleDateFormat sdf = null; 54 private String nowDatetime = null ; //当前系统日期字符串 55 56 57 /** 58 * 带参数的构造函数,该构造函数将构造一个设置了日历控件的载体组件的CalenderPanel对象实例 59 * @param component 日历控件的载体组件,可以是TextField、JTextField、Label、JLabel 60 * @param patern 日期格式 ,默认为yyyy-MM-dd 61 */ 62 public CalendarPanel(Object component,String patern) { 63 this(patern); 64 this.component = component; 65 } 66 67 68 /** 69 * 带参数的构造函数,该构造函数将构造一个CalenderPanel对象实例,该对象时候没有设置日历控件的载体组件 70 * * @param patern 日期格式,默认为yyyy-MM-dd 71 */ 72 public CalendarPanel(String patern) { 73 super(); 74 75 //初始化日期格式化 76 this.patern = patern; 77 sdf = new SimpleDateFormat(patern); 78 nowDatetime = sdf.format(new Date()); 79 80 setLayout(null); 81 //设置日历控件的整体主面板边框为灰色 82 this.setBorder(BorderFactory.createLineBorder(Color.gray)); 83 //初始化日历控件上的各个组件 84 init(); 85 //创建日历控件的日期部分面板 86 createCalendarPanel(nowDatetime); 87 } 88 89 /** 90 * 无参数的构造函数,该构造函数将构造一个CalenderPanel对象实例,该对象时候没有设置日历控件的载体组件 91 */ 92 public CalendarPanel() { 93 super(); 94 95 //初始化日期格式化 96 sdf = new SimpleDateFormat(patern); 97 nowDatetime = sdf.format(new Date()); 98 99 setLayout(null); 100 //设置日历控件的整体主面板边框为灰色 101 this.setBorder(BorderFactory.createLineBorder(Color.gray)); 102 //初始化日历控件上的各个组件 103 init(); 104 //创建日历控件的日期部分面板 105 createCalendarPanel(nowDatetime); 106 } 107 108 /** 109 * 获取日历控件的载体组件 110 * @return 返回该日历控件中的载体组件,如果没有设置,则返回null; 111 */ 112 public Object getComponent() { 113 return component; 114 } 115 116 /** 117 * 设置日历控件的载体组件 118 * @param component 119 */ 120 public void setComponent(Object component) { 121 this.component = component; 122 } 123 124 /** 125 * 获取选择日期时候的日期字符串 126 * @return 127 */ 128 public String getReturnDateStr() { 129 return returnDateStr; 130 } 131 132 /** 133 * 获取日历控件的回调接口对象 134 * @return 135 */ 136 public CallBack getCallBack() { 137 return callBack; 138 } 139 140 /** 141 * 设置日历控件的回调接口对象 142 * @param callBack 143 */ 144 public void setCallBack(CallBack callBack) { 145 this.callBack = callBack; 146 } 147 148 149 /** 150 * 创建下拉选择日历控件的主体面板(即显示日期部分的面板) 151 * @param date 需要显示的日期 152 */ 153 private void createCalendarPanel(String date){ 154 //每次刷新日期显示,需要重新创建日期部分的面板 155 //如果日期部分的面板不为null,可以先将其remove,然后再创建 156 if(panel_maincalenderpanel!=null){ 157 panel_maincalenderpanel.setVisible(false); 158 this.remove(panel_maincalenderpanel); 159 } 160 161 //创建新的日期部分的面板 162 panel_maincalenderpanel = new JPanel(); 163 panel_maincalenderpanel.setBackground(Color.WHITE); 164 panel_maincalenderpanel.setBounds(2, 47, 247, 156); 165 panel_maincalenderpanel.setLayout(new GridLayout(6,7)); 166 add(panel_maincalenderpanel); 167 168 Date today = null; 169 try { 170 today = sdf.parse(date); 171 } catch (ParseException e1) { 172 e1.printStackTrace(); 173 return; 174 } 175 176 Calendar c = new GregorianCalendar(); 177 //将给定日期设置为需要显示的日期 178 c.setTime(today); 179 //需要将日改成1号,因为我们需要获取给定日期的第一天是星期几 180 c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH), 1); 181 182 int firstDayInMonthOfWeek = c.get(Calendar.DAY_OF_WEEK); //给定日期的第一天是星期几 183 int daysOfMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH); //给定日期对应月份的天数 184 185 //首先生成给定日期第一天之前的空白部分 186 //例如:2011-11的第一天就是星期二,那么星期二之前的(星期日,星期一)我们不显示内容,需要生成空白 187 for(int i=1;i<firstDayInMonthOfWeek;i++){ 188 JLabel bnt = new JLabel(""); 189 bnt.setSize(27,23); 190 bnt.setBackground(Color.WHITE); 191 panel_maincalenderpanel.add(bnt); 192 } 193 194 //然后生成给定日期的日期部分,即输出1,2,3....31这样的日期 195 for(int i=1;i<=daysOfMonth;i++){ 196 final JLabel bnt = new JLabel(String.valueOf(i)); 197 bnt.setHorizontalAlignment(SwingConstants.CENTER); 198 bnt.setSize(27,23); 199 bnt.setBackground(Color.WHITE); 200 if(Calendar.getInstance().get(Calendar.DATE)==i){ 201 //将系统当期日期对应的组件的边框显示为绿色 202 bnt.setBorder(BorderFactory.createLineBorder(Color.GREEN)); 203 }else{ 204 //其他的日期组件边框显示为白色 205 bnt.setBorder(BorderFactory.createLineBorder(Color.WHITE)); 206 } 207 208 //为定义的日期组件添加鼠标事件 209 bnt.addMouseListener(new MouseAdapter() { 210 @Override 211 public void mouseEntered(MouseEvent e) { 212 //当鼠标经过对应的日期上面时候,该日期对应的组件边框显示成绿色 213 bnt.setBorder(BorderFactory.createLineBorder(Color.GREEN)); 214 } 215 216 @Override 217 public void mouseExited(MouseEvent e) { 218 if(Calendar.getInstance().get(Calendar.DATE)==Integer.parseInt(((JLabel)e.getSource()).getText().trim())){ 219 //当鼠标离开对应日期组件时候,系统当期日期对应的组件的边框显示为绿色 220 bnt.setBorder(BorderFactory.createLineBorder(Color.GREEN)); 221 }else{ 222 //其他的日期对应的组件边框为白色 223 bnt.setBorder(BorderFactory.createLineBorder(Color.WHITE)); 224 } 225 } 226 227 @Override 228 public void mouseClicked(MouseEvent e) { 229 230 //鼠标单击事件,当鼠标选择某个日期时候,需要将对应的日期按照给定的日期格式填充到日历控件的载体组件上,即setText(..) 231 String dateStr = lb_datetime.getText().trim(); 232 try { 233 dateStr = sdf.format(sdf.parse(dateStr)); 234 dateStr = dateStr.substring(0,dateStr.length()-2); 235 if (component instanceof java.awt.TextField){ 236 TextField txt = (TextField)component; 237 dateStr += ((JLabel)e.getSource()).getText().trim(); 238 dateStr = sdf.format(sdf.parse(dateStr)); 239 txt.setText(dateStr); 240 } 241 if (component instanceof java.awt.Label){ 242 Label label = (Label)component; 243 dateStr += ((JLabel)e.getSource()).getText().trim(); 244 dateStr = sdf.format(sdf.parse(dateStr)); 245 label.setText(dateStr); 246 247 } 248 if (component instanceof javax.swing.JTextField){ 249 JTextField txt = (JTextField)component; 250 dateStr += ((JLabel)e.getSource()).getText().trim(); 251 dateStr = sdf.format(sdf.parse(dateStr)); 252 txt.setText(dateStr); 253 254 } 255 if (component instanceof javax.swing.JLabel){ 256 JLabel label = (JLabel)component; 257 dateStr += ((JLabel)e.getSource()).getText().trim(); 258 dateStr = sdf.format(sdf.parse(dateStr)); 259 label.setText(dateStr); 260 } 261 262 } catch (ParseException e2) { 263 e2.printStackTrace(); 264 } 265 266 267 268 //为了能够让那个载体组件自用空,这里也需要设置returnDateStr并调用回调接口 269 returnDateStr = dateStr; 270 if(callBack!=null){ 271 callBack.callback(); 272 } 273 274 //选择日期后需要将日历控件隐藏 275 CalendarPanel.this.setVisible(false); 276 277 } 278 279 280 }); 281 panel_maincalenderpanel.add(bnt); 282 } 283 284 for(int i=1;i<6*7-(firstDayInMonthOfWeek-1)-daysOfMonth;i++){ 285 JLabel bnt = new JLabel(""); 286 bnt.setSize(27,23); 287 bnt.setBackground(Color.WHITE); 288 panel_maincalenderpanel.add(bnt); 289 } 290 291 panel_maincalenderpanel.validate(); 292 } 293 294 295 296 /** 297 * 初始化所有控件 298 */ 299 private void init(){ 300 //上一年操作组件,这里使用一个JLabel 301 btn_lastYear = new JLabel("<<"); 302 btn_lastYear.setBounds(10, 0, 27, 23); 303 add(btn_lastYear); 304 btn_lastYear.addMouseListener(new MouseAdapter() { 305 306 @Override 307 public void mouseClicked(MouseEvent e) { 308 //改变日历控件面板的显示日期 309 changTheDate(Calendar.YEAR,false); 310 } 311 312 }); 313 314 //下一年操作组件,这里使用一个JLabel 315 btn_nextYear = new JLabel(">>"); 316 btn_nextYear.setBounds(179, 0, 27, 23); 317 add(btn_nextYear); 318 btn_nextYear.addMouseListener(new MouseAdapter() { 319 320 @Override 321 public void mouseClicked(MouseEvent e) { 322 //改变日历控件面板的显示日期 323 changTheDate(Calendar.YEAR,true); 324 } 325 326 }); 327 328 //上一月操作组件,这里使用一个JLabel 329 btn_lastMonth = new JLabel("<"); 330 btn_lastMonth.setBounds(39, 0, 27, 23); 331 add(btn_lastMonth); 332 btn_lastMonth.addMouseListener(new MouseAdapter() { 333 334 @Override 335 public void mouseClicked(MouseEvent e) { 336 //改变日历控件面板的显示日期 337 changTheDate(Calendar.MONTH,false); 338 } 339 340 }); 341 342 //下一月操作组件,这里使用一个JLabel 343 btn_nextMonth = new JLabel(">"); 344 btn_nextMonth.setBounds(150, 0, 27, 23); 345 add(btn_nextMonth); 346 btn_nextMonth.addMouseListener(new MouseAdapter() { 347 348 @Override 349 public void mouseClicked(MouseEvent e) { 350 //改变日历控件面板的显示日期 351 changTheDate(Calendar.MONTH,true); 352 } 353 354 }); 355 356 //显示日期的lable对象 357 lb_datetime = new JLabel(""); 358 lb_datetime.setBounds(58, 2, 86, 19); 359 lb_datetime.setHorizontalAlignment(SwingConstants.CENTER); 360 add(lb_datetime); 361 lb_datetime.setText(nowDatetime); 362 363 lblNewLabel = new JLabel("日"); 364 lblNewLabel.setForeground(Color.RED); 365 lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER); 366 lblNewLabel.setBounds(2, 22, 27, 23); 367 add(lblNewLabel); 368 369 label = new JLabel("一"); 370 label.setHorizontalAlignment(SwingConstants.CENTER); 371 label.setBounds(39, 22, 27, 23); 372 add(label); 373 374 label_1 = new JLabel("二"); 375 label_1.setHorizontalAlignment(SwingConstants.CENTER); 376 label_1.setBounds(76, 22, 27, 23); 377 add(label_1); 378 379 label_2 = new JLabel("三"); 380 label_2.setHorizontalAlignment(SwingConstants.CENTER); 381 label_2.setBounds(113, 22, 27, 23); 382 add(label_2); 383 384 label_3 = new JLabel("四"); 385 label_3.setHorizontalAlignment(SwingConstants.CENTER); 386 label_3.setBounds(147, 22, 27, 23); 387 add(label_3); 388 389 label_4 = new JLabel("五"); 390 label_4.setHorizontalAlignment(SwingConstants.CENTER); 391 label_4.setBounds(184, 22, 27, 23); 392 add(label_4); 393 394 label_5 = new JLabel("六"); 395 label_5.setForeground(Color.GREEN); 396 label_5.setHorizontalAlignment(SwingConstants.CENTER); 397 label_5.setBounds(221, 22, 27, 23); 398 add(label_5); 399 400 btn_close = new JLabel("[X]"); 401 btn_close.setBounds(222, 0, 27, 23); 402 btn_close.setForeground(Color.RED); 403 add(btn_close); 404 btn_close.addMouseListener(new MouseAdapter() { 405 406 @Override 407 public void mouseClicked(MouseEvent e) { 408 CalendarPanel.this.setVisible(false); 409 } 410 411 }); 412 413 414 //用于快速显示今天日期的按钮 415 btn_today = new JButton("今天"); 416 btn_today.setBounds(10, 213, 60, 23); 417 btn_today.setContentAreaFilled(false); 418 btn_today.setBorder(BorderFactory.createLineBorder(Color.GRAY)); 419 add(btn_today); 420 btn_today.addActionListener(new ActionListener() { 421 @Override 422 public void actionPerformed(ActionEvent e) { 423 createCalendarPanel(nowDatetime); 424 lb_datetime.setText(nowDatetime); 425 } 426 }); 427 428 429 //用于取消日期选择的按钮 430 btn_cancel = new JButton("取消"); 431 btn_cancel.setBounds(179, 213, 60, 23); 432 btn_cancel.setContentAreaFilled(false); 433 btn_cancel.setBorder(BorderFactory.createLineBorder(Color.GRAY)); 434 add(btn_cancel); 435 btn_cancel.addActionListener(new ActionListener() { 436 @Override 437 public void actionPerformed(ActionEvent e) { 438 CalendarPanel.this.setVisible(false); 439 } 440 }); 441 } 442 443 /** 444 * 重新设置日历面板显示为系统当前日期 445 */ 446 public void reset(){ 447 createCalendarPanel(nowDatetime); 448 lb_datetime.setText(nowDatetime); 449 } 450 451 452 453 /** 454 * 改变当前日历控件面板的日期显示 455 * @param YEAR_OR_MONTH 是对YEAR还是MONTH操作,这里需要传入Calendar类对应的常量值:Calendar.YEAR,Calendar.MONTH 456 * @param flag 对YEAR_OR_MONTH属性是进行加法操作还是减法操作,如果flag为true则是加法操作,否则为减法操作 457 */ 458 public void changTheDate(int YEAR_OR_MONTH,boolean flag){ 459 String dateStr = lb_datetime.getText().trim(); 460 Date date = null; 461 try { 462 date = sdf.parse(dateStr); 463 } catch (ParseException e1) { 464 e1.printStackTrace(); 465 return; 466 } 467 Calendar c = Calendar.getInstance(); 468 c.setTime(date); 469 if(flag){ 470 //将对应的日期属性进行加法操作 471 c.set(YEAR_OR_MONTH,c.get(YEAR_OR_MONTH)+1 ); 472 }else{ 473 //将对应的日期属性进行减法操作 474 c.set(YEAR_OR_MONTH,c.get(YEAR_OR_MONTH)-1 ); 475 } 476 477 date = c.getTime(); 478 lb_datetime.setText(sdf.format(date)); 479 createCalendarPanel(sdf.format(date)); 480 } 481 482 483 484 public static void main(String[] args) { 485 Calendar c = new GregorianCalendar(2011,11,1); 486 System.out.println( c.get(Calendar.DAY_OF_WEEK)); 487 } 488 489 490 public void initCalendarPanel(){ 491 if(component instanceof javax.swing.JComponent){ 492 JComponent j = (JComponent)component; 493 int w = j.getWidth(); 494 int h = j.getHeight(); 495 int x = j.getX(); 496 int y = j.getY(); 497 System.out.println("with:"+w +"height:"+h+"x:"+x+"y:"+y); 498 this.setComponent(component); 499 this.setBounds((x), y+h, 251, 245); 500 this.setVisible(false); 501 j.addMouseListener(new MouseAdapter() { 502 @Override 503 public void mouseClicked(MouseEvent e) { 504 if (CalendarPanel.this.isVisible()){ 505 CalendarPanel.this.setVisible(false); 506 }else{ 507 CalendarPanel.this.setVisible(true); 508 CalendarPanel.this.reset(); 509 } 510 } 511 }); 512 } 513 } 514 515 516 517 }
接口:
1 package com.ryd.stocktrader.client.util; 2 3 /** 4 * Created by Administrator on 2016/7/28. 5 */ 6 public interface CallBack { 7 public void callback(); 8 }
测试类:
1 import java.awt.Color; 2 import java.awt.Point; 3 4 import javax.swing.JFrame; 5 import javax.swing.JLabel; 6 import javax.swing.JPanel; 7 import javax.swing.JTextField; 8 9 //测试类 10 public class DateChooser extends JPanel { 11 /** 12 * 13 */ 14 private static final long serialVersionUID = 1L; 15 //private static Point startp = null; 16 //private Point endp = null; 17 18 public static void main(String[] args) { 19 20 JFrame f = new JFrame(); 21 f.setLayout(null); 22 JTextField txt1 = new JTextField(); 23 JTextField txt2 = new JTextField(); 24 txt1.setBounds(20, 50, 300, 30); 25 txt2.setBounds(20, 80, 300, 30); 26 27 // 定义日历控件面板类 28 CalendarPanel p = new CalendarPanel(txt1, "yyyy/MM/dd"); 29 p.initCalendarPanel(); 30 31 JLabel l = new JLabel("日历面板"); 32 p.add(l); 33 f.getContentPane().add(p); 34 f.getContentPane().add(txt1); 35 f.getContentPane().add(txt2); 36 f.setSize(500, 400); 37 f.setBackground(Color.WHITE); 38 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 39 f.setVisible(true); 40 } 41 }
方式二:
1 package com.ryd.stocktrader.client.util; 2 3 import java.awt.BasicStroke; 4 5 import java.awt.BorderLayout; 6 7 import java.awt.Color; 8 9 import java.awt.Component; 10 11 import java.awt.Cursor; 12 13 import java.awt.Dimension; 14 15 import java.awt.Font; 16 17 import java.awt.Graphics; 18 19 import java.awt.Graphics2D; 20 21 import java.awt.GridLayout; 22 23 import java.awt.Point; 24 25 import java.awt.Polygon; 26 27 import java.awt.Stroke; 28 29 import java.awt.Toolkit; 30 31 import java.awt.event.FocusEvent; 32 33 import java.awt.event.FocusListener; 34 35 import java.awt.event.MouseAdapter; 36 37 import java.awt.event.MouseEvent; 38 39 import java.awt.event.MouseListener; 40 41 import java.awt.event.MouseMotionListener; 42 43 import java.text.SimpleDateFormat; 44 45 import java.util.ArrayList; 46 47 import java.util.Calendar; 48 49 import java.util.Comparator; 50 51 import java.util.Date; 52 53 import java.util.List; 54 55 56 57 import javax.swing.BorderFactory; 58 59 import javax.swing.JComponent; 60 61 import javax.swing.JFrame; 62 63 import javax.swing.JLabel; 64 65 import javax.swing.JPanel; 66 67 import javax.swing.JTextField; 68 69 import javax.swing.Popup; 70 71 import javax.swing.PopupFactory; 72 73 import javax.swing.SwingUtilities; 74 75 import javax.swing.event.AncestorEvent; 76 77 import javax.swing.event.AncestorListener; 78 79 public class DateChooser extends JPanel { 80 private static final long serialVersionUID = 4529266044762990227L; 81 82 83 84 private Date initDate; 85 86 private Calendar now = Calendar.getInstance(); 87 88 private Calendar select; 89 90 private JPanel monthPanel;//月历 91 92 private JP1 jp1;//四块面板,组成 93 94 private JP2 jp2; 95 96 private JP3 jp3; 97 98 private JP4 jp4; 99 100 private Font font = new Font("宋体", Font.PLAIN, 12); 101 102 private final LabelManager lm = new LabelManager(); 103 104 private SimpleDateFormat sdf; 105 106 private boolean isShow = false; 107 108 private Popup pop; 109 110 111 112 private JComponent showDate; 113 114 115 116 public static DateChooser getInstance() { 117 118 return new DateChooser(); 119 120 } 121 122 123 124 public static DateChooser getInstance(Date date) { 125 126 return new DateChooser(date); 127 128 } 129 130 131 132 public static DateChooser getInstance(String format) { 133 134 return new DateChooser(format); 135 136 } 137 138 139 140 public static DateChooser getInstance(Date date, String format) { 141 142 return new DateChooser(date, format); 143 144 } 145 146 147 148 /** 149 150 * Creates a new instance of DateChooser 151 152 */ 153 154 private DateChooser() { 155 156 this(new Date()); 157 158 } 159 160 161 162 private DateChooser(Date date) { 163 164 this(date, "yyyy年MM月dd日"); 165 166 } 167 168 169 170 private DateChooser(String format) { 171 172 this(new Date(), format); 173 174 } 175 176 177 178 private DateChooser(Date date, String format) { 179 180 initDate = date; 181 182 sdf = new SimpleDateFormat(format); 183 184 select = Calendar.getInstance(); 185 186 select.setTime(initDate); 187 188 initPanel(); 189 190 } 191 192 193 194 /** 195 196 * 是否允许用户选择 197 198 */ 199 200 public void setEnabled(boolean b) { 201 202 super.setEnabled(b); 203 204 showDate.setEnabled(b); 205 206 } 207 208 209 210 /** 211 212 *得到当前选择框的日期 213 214 */ 215 216 public Date getDate() { 217 218 return select.getTime(); 219 220 } 221 222 223 224 public String getStrDate() { 225 226 return sdf.format(select.getTime()); 227 228 } 229 230 231 232 public String getStrDate(String format) { 233 234 sdf = new SimpleDateFormat(format); 235 236 return sdf.format(select.getTime()); 237 238 } 239 240 241 242 //根据初始化的日期,初始化面板 243 244 private void initPanel() { 245 246 monthPanel = new JPanel(new BorderLayout()); 247 248 monthPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE)); 249 250 JPanel up = new JPanel(new BorderLayout()); 251 252 up.add(jp1 = new JP1(), BorderLayout.NORTH); 253 254 up.add(jp2 = new JP2(), BorderLayout.CENTER); 255 256 monthPanel.add(jp3 = new JP3(), BorderLayout.CENTER); 257 258 monthPanel.add(up, BorderLayout.NORTH); 259 260 monthPanel.add(jp4 = new JP4(), BorderLayout.SOUTH); 261 262 this.addAncestorListener(new AncestorListener() { 263 264 public void ancestorAdded(AncestorEvent event) { 265 266 267 268 } 269 270 271 272 public void ancestorRemoved(AncestorEvent event) { 273 274 275 276 } 277 278 279 280 //只要祖先组件一移动,马上就让popup消失 281 282 public void ancestorMoved(AncestorEvent event) { 283 284 hidePanel(); 285 286 } 287 288 }); 289 290 } 291 292 293 294 public void register(final JComponent showDate) { 295 296 this.showDate = showDate; 297 298 299 300 showDate.setRequestFocusEnabled(true); 301 302 showDate.addMouseListener(new MouseAdapter() { 303 304 public void mousePressed(MouseEvent me) { 305 306 showDate.requestFocusInWindow(); 307 308 } 309 310 }); 311 312 this.setBackground(Color.WHITE); 313 314 this.add(showDate, BorderLayout.CENTER); 315 316 this.setPreferredSize(new Dimension(90, 25)); 317 318 this.setBorder(BorderFactory.createLineBorder(Color.GRAY)); 319 320 showDate.addMouseListener(new MouseAdapter() { 321 322 public void mouseEntered(MouseEvent me) { 323 324 if (showDate.isEnabled()) { 325 326 showDate.setCursor(new Cursor(Cursor.HAND_CURSOR)); 327 328 showDate.setForeground(Color.white); 329 330 } 331 332 } 333 334 335 336 public void mouseExited(MouseEvent me) { 337 338 if (showDate.isEnabled()) { 339 340 showDate.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 341 342 showDate.setForeground(Color.white); 343 344 } 345 346 } 347 348 349 350 public void mousePressed(MouseEvent me) { 351 352 if (showDate.isEnabled()) { 353 354 showDate.setForeground(Color.CYAN); 355 356 if (isShow) { 357 358 hidePanel(); 359 360 } else { 361 362 showPanel(showDate); 363 364 } 365 366 } 367 368 } 369 370 371 372 public void mouseReleased(MouseEvent me) { 373 374 if (showDate.isEnabled()) { 375 376 showDate.setForeground(Color.BLACK); 377 378 } 379 380 } 381 382 }); 383 384 showDate.addFocusListener(new FocusListener() { 385 386 public void focusLost(FocusEvent e) { 387 388 hidePanel(); 389 390 } 391 392 393 394 public void focusGained(FocusEvent e) { 395 396 397 398 } 399 400 }); 401 402 } 403 404 405 406 //根据新的日期刷新 407 408 private void refresh() { 409 410 jp1.updateDate(); 411 412 jp2.updateDate(); 413 414 jp3.updateDate(); 415 416 jp4.updateDate(); 417 418 SwingUtilities.updateComponentTreeUI(this); 419 420 } 421 422 423 424 //提交日期 425 426 private void commit() { 427 428 //TODO add other components here 429 430 if (showDate instanceof JTextField) { 431 432 ((JTextField) showDate).setText(sdf.format(select.getTime())); 433 434 }else if (showDate instanceof JLabel) { 435 436 ((JLabel) showDate).setText(sdf.format(select.getTime())); 437 438 } 439 440 441 442 hidePanel(); 443 444 } 445 446 447 448 //隐藏日期选择面板 449 450 private void hidePanel() { 451 452 if (pop != null) { 453 454 isShow = false; 455 456 pop.hide(); 457 458 pop = null; 459 460 } 461 462 } 463 464 465 466 //显示日期选择面板 467 468 private void showPanel(Component owner) { 469 470 if (pop != null) { 471 472 pop.hide(); 473 474 } 475 476 Point show = new Point(0, showDate.getHeight()); 477 478 SwingUtilities.convertPointToScreen(show, showDate); 479 480 Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); 481 482 int x = show.x; 483 484 int y = show.y; 485 486 if (x < 0) { 487 488 x = 0; 489 490 } 491 492 if (x > size.width - 295) { 493 494 x = size.width - 295; 495 496 } 497 498 if (y < size.height - 170) { 499 500 } else { 501 502 y -= 188; 503 504 } 505 506 pop = PopupFactory.getSharedInstance().getPopup(owner, monthPanel, x, y); 507 508 pop.show(); 509 510 isShow = true; 511 512 } 513 514 515 516 /** 517 518 * 最上面的面板用来显示月份的增减 519 520 */ 521 522 private class JP1 extends JPanel { 523 524 private static final long serialVersionUID = -5638853772805561174L; 525 526 JLabel yearleft, yearright, monthleft, monthright, center, centercontainer; 527 528 529 530 public JP1() { 531 532 super(new BorderLayout()); 533 534 this.setBackground(new Color(160, 185, 215)); 535 536 initJP1(); 537 538 } 539 540 541 542 private void initJP1() { 543 544 yearleft = new JLabel(" <<", JLabel.CENTER); 545 546 yearleft.setToolTipText("上一年"); 547 548 yearright = new JLabel(">> ", JLabel.CENTER); 549 550 yearright.setToolTipText("下一年"); 551 552 yearleft.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); 553 554 yearright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); 555 556 557 558 monthleft = new JLabel(" <", JLabel.RIGHT); 559 560 monthleft.setToolTipText("上一月"); 561 562 monthright = new JLabel("> ", JLabel.LEFT); 563 564 monthright.setToolTipText("下一月"); 565 566 monthleft.setBorder(BorderFactory.createEmptyBorder(2, 30, 0, 0)); 567 568 monthright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 30)); 569 570 571 572 centercontainer = new JLabel("", JLabel.CENTER); 573 574 centercontainer.setLayout(new BorderLayout()); 575 576 center = new JLabel("", JLabel.CENTER); 577 578 579 580 centercontainer.add(monthleft, BorderLayout.WEST); 581 582 centercontainer.add(center, BorderLayout.CENTER); 583 584 centercontainer.add(monthright, BorderLayout.EAST); 585 586 587 588 this.add(yearleft, BorderLayout.WEST); 589 590 this.add(centercontainer, BorderLayout.CENTER); 591 592 this.add(yearright, BorderLayout.EAST); 593 594 this.setPreferredSize(new Dimension(295, 25)); 595 596 597 598 updateDate(); 599 600 601 602 yearleft.addMouseListener(new MouseAdapter() { 603 604 public void mouseEntered(MouseEvent me) { 605 606 yearleft.setCursor(new Cursor(Cursor.HAND_CURSOR)); 607 608 yearleft.setForeground(Color.RED); 609 610 } 611 612 613 614 public void mouseExited(MouseEvent me) { 615 616 yearleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 617 618 yearleft.setForeground(Color.BLACK); 619 620 } 621 622 623 624 public void mousePressed(MouseEvent me) { 625 626 select.add(Calendar.YEAR, -1); 627 628 yearleft.setForeground(Color.WHITE); 629 630 refresh(); 631 632 } 633 634 635 636 public void mouseReleased(MouseEvent me) { 637 638 yearleft.setForeground(Color.BLACK); 639 640 } 641 642 }); 643 644 yearright.addMouseListener(new MouseAdapter() { 645 646 public void mouseEntered(MouseEvent me) { 647 648 yearright.setCursor(new Cursor(Cursor.HAND_CURSOR)); 649 650 yearright.setForeground(Color.RED); 651 652 } 653 654 655 656 public void mouseExited(MouseEvent me) { 657 658 yearright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 659 660 yearright.setForeground(Color.BLACK); 661 662 } 663 664 665 666 public void mousePressed(MouseEvent me) { 667 668 select.add(Calendar.YEAR, 1); 669 670 yearright.setForeground(Color.WHITE); 671 672 refresh(); 673 674 } 675 676 677 678 public void mouseReleased(MouseEvent me) { 679 680 yearright.setForeground(Color.BLACK); 681 682 } 683 684 }); 685 686 monthleft.addMouseListener(new MouseAdapter() { 687 688 public void mouseEntered(MouseEvent me) { 689 690 monthleft.setCursor(new Cursor(Cursor.HAND_CURSOR)); 691 692 monthleft.setForeground(Color.RED); 693 694 } 695 696 697 698 public void mouseExited(MouseEvent me) { 699 700 monthleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 701 702 monthleft.setForeground(Color.BLACK); 703 704 } 705 706 707 708 public void mousePressed(MouseEvent me) { 709 710 select.add(Calendar.MONTH, -1); 711 712 monthleft.setForeground(Color.WHITE); 713 714 refresh(); 715 716 } 717 718 719 720 public void mouseReleased(MouseEvent me) { 721 722 monthleft.setForeground(Color.BLACK); 723 724 } 725 726 }); 727 728 monthright.addMouseListener(new MouseAdapter() { 729 730 public void mouseEntered(MouseEvent me) { 731 732 monthright.setCursor(new Cursor(Cursor.HAND_CURSOR)); 733 734 monthright.setForeground(Color.RED); 735 736 } 737 738 739 740 public void mouseExited(MouseEvent me) { 741 742 monthright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 743 744 monthright.setForeground(Color.BLACK); 745 746 } 747 748 749 750 public void mousePressed(MouseEvent me) { 751 752 select.add(Calendar.MONTH, 1); 753 754 monthright.setForeground(Color.WHITE); 755 756 refresh(); 757 758 } 759 760 761 762 public void mouseReleased(MouseEvent me) { 763 764 monthright.setForeground(Color.BLACK); 765 766 } 767 768 }); 769 770 } 771 772 773 774 private void updateDate() { 775 776 center.setText(select.get(Calendar.YEAR) + "年" + (select.get(Calendar.MONTH) + 1) + "月"); 777 778 } 779 780 } 781 782 783 784 private class JP2 extends JPanel { 785 786 private static final long serialVersionUID = -8176264838786175724L; 787 788 789 790 public JP2() { 791 792 this.setPreferredSize(new Dimension(295, 20)); 793 794 } 795 796 797 798 protected void paintComponent(Graphics g) { 799 800 g.setFont(font); 801 802 g.drawString("星期日 星期一 星期二 星期三 星期四 星期五 星期六", 5, 10); 803 804 g.drawLine(0, 15, getWidth(), 15); 805 806 } 807 808 809 810 private void updateDate() { 811 812 813 814 } 815 816 } 817 818 819 820 private class JP3 extends JPanel { 821 822 private static final long serialVersionUID = 43157272447522985L; 823 824 825 826 public JP3() { 827 828 super(new GridLayout(6, 7)); 829 830 this.setPreferredSize(new Dimension(295, 100)); 831 832 initJP3(); 833 834 } 835 836 837 838 private void initJP3() { 839 840 updateDate(); 841 842 } 843 844 845 846 public void updateDate() { 847 848 this.removeAll(); 849 850 lm.clear(); 851 852 Date temp = select.getTime(); 853 854 Calendar select = Calendar.getInstance(); 855 856 select.setTime(temp); 857 858 select.set(Calendar.DAY_OF_MONTH, 1); 859 860 int index = select.get(Calendar.DAY_OF_WEEK); 861 862 int sum = (index == 1 ? 8 : index); 863 864 select.add(Calendar.DAY_OF_MONTH, 0 - sum); 865 866 for (int i = 0; i < 42; i++) { 867 868 select.add(Calendar.DAY_OF_MONTH, 1); 869 870 lm.addLabel(new MyLabel(select.get(Calendar.YEAR), select.get(Calendar.MONTH), select.get(Calendar.DAY_OF_MONTH))); 871 872 } 873 874 for (MyLabel my : lm.getLabels()) { 875 876 this.add(my); 877 878 } 879 880 select.setTime(temp); 881 882 } 883 884 } 885 886 887 888 private class MyLabel extends JLabel implements Comparator<MyLabel>, MouseListener, MouseMotionListener { 889 890 private static final long serialVersionUID = 3668734399227577214L; 891 892 private int year, month, day; 893 894 private boolean isSelected; 895 896 897 898 public MyLabel(int year, int month, int day) { 899 900 super("" + day, JLabel.CENTER); 901 902 this.year = year; 903 904 this.day = day; 905 906 this.month = month; 907 908 this.addMouseListener(this); 909 910 this.addMouseMotionListener(this); 911 912 this.setFont(font); 913 914 if (month == select.get(Calendar.MONTH)) { 915 916 this.setForeground(Color.BLACK); 917 918 } else { 919 920 this.setForeground(Color.LIGHT_GRAY); 921 922 } 923 924 if (day == select.get(Calendar.DAY_OF_MONTH)) { 925 926 this.setBackground(new Color(160, 185, 215)); 927 928 } else { 929 930 this.setBackground(Color.WHITE); 931 932 } 933 934 } 935 936 937 938 public boolean getIsSelected() { 939 940 return isSelected; 941 942 } 943 944 945 946 public void setSelected(boolean b, boolean isDrag) { 947 948 isSelected = b; 949 950 if (b && !isDrag) { 951 952 int temp = select.get(Calendar.MONTH); 953 954 select.set(year, month, day); 955 956 if (temp == month) { 957 958 SwingUtilities.updateComponentTreeUI(jp3); 959 960 } else { 961 962 refresh(); 963 964 } 965 966 } 967 968 this.repaint(); 969 970 } 971 972 973 974 protected void paintComponent(Graphics g) { 975 976 if (day == select.get(Calendar.DAY_OF_MONTH) && month == select.get(Calendar.MONTH)) { 977 978 //如果当前日期是选择日期,则高亮显示 979 980 g.setColor(new Color(160, 185, 215)); 981 982 g.fillRect(0, 0, getWidth(), getHeight()); 983 984 } 985 986 if (year == now.get(Calendar.YEAR) && month == now.get(Calendar.MONTH) && day == now.get(Calendar.DAY_OF_MONTH)) { 987 988 //如果日期和当前日期一样,则用红框 989 990 Graphics2D gd = (Graphics2D) g; 991 992 gd.setColor(Color.RED); 993 994 Polygon p = new Polygon(); 995 996 p.addPoint(0, 0); 997 998 p.addPoint(getWidth() - 1, 0); 999 1000 p.addPoint(getWidth() - 1, getHeight() - 1); 1001 1002 p.addPoint(0, getHeight() - 1); 1003 1004 gd.drawPolygon(p); 1005 1006 } 1007 1008 if (isSelected) {//如果被选中了就画出一个虚线框出来 1009 1010 Stroke s = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, new float[] { 2.0f, 2.0f }, 1.0f); 1011 1012 Graphics2D gd = (Graphics2D) g; 1013 1014 gd.setStroke(s); 1015 1016 gd.setColor(Color.BLACK); 1017 1018 Polygon p = new Polygon(); 1019 1020 p.addPoint(0, 0); 1021 1022 p.addPoint(getWidth() - 1, 0); 1023 1024 p.addPoint(getWidth() - 1, getHeight() - 1); 1025 1026 p.addPoint(0, getHeight() - 1); 1027 1028 gd.drawPolygon(p); 1029 1030 } 1031 1032 super.paintComponent(g); 1033 1034 } 1035 1036 1037 1038 public boolean contains(Point p) { 1039 1040 return this.getBounds().contains(p); 1041 1042 } 1043 1044 1045 1046 private void update() { 1047 1048 repaint(); 1049 1050 } 1051 1052 1053 1054 public void mouseClicked(MouseEvent e) { 1055 1056 } 1057 1058 1059 1060 public void mousePressed(MouseEvent e) { 1061 1062 isSelected = true; 1063 1064 update(); 1065 1066 } 1067 1068 1069 1070 public void mouseReleased(MouseEvent e) { 1071 1072 Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3); 1073 1074 lm.setSelect(p, false); 1075 1076 commit(); 1077 1078 } 1079 1080 1081 1082 public void mouseEntered(MouseEvent e) { 1083 1084 } 1085 1086 1087 1088 public void mouseExited(MouseEvent e) { 1089 1090 } 1091 1092 1093 1094 public void mouseDragged(MouseEvent e) { 1095 1096 Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3); 1097 1098 lm.setSelect(p, true); 1099 1100 } 1101 1102 1103 1104 public void mouseMoved(MouseEvent e) { 1105 1106 } 1107 1108 1109 1110 public int compare(MyLabel o1, MyLabel o2) { 1111 1112 Calendar c1 = Calendar.getInstance(); 1113 1114 c1.set(o1.year, o2.month, o1.day); 1115 1116 Calendar c2 = Calendar.getInstance(); 1117 1118 c2.set(o2.year, o2.month, o2.day); 1119 1120 return c1.compareTo(c2); 1121 1122 } 1123 1124 } 1125 1126 1127 1128 private class LabelManager { 1129 1130 private List<MyLabel> list; 1131 1132 1133 1134 public LabelManager() { 1135 1136 list = new ArrayList<MyLabel>(); 1137 1138 } 1139 1140 1141 1142 public List<MyLabel> getLabels() { 1143 1144 return list; 1145 1146 } 1147 1148 1149 1150 public void addLabel(MyLabel my) { 1151 1152 list.add(my); 1153 1154 } 1155 1156 1157 1158 public void clear() { 1159 1160 list.clear(); 1161 1162 } 1163 1164 1165 1166 @SuppressWarnings("unused") 1167 1168 public void setSelect(MyLabel my, boolean b) { 1169 1170 for (MyLabel m : list) { 1171 1172 if (m.equals(my)) { 1173 1174 m.setSelected(true, b); 1175 1176 } else { 1177 1178 m.setSelected(false, b); 1179 1180 } 1181 1182 } 1183 1184 } 1185 1186 1187 1188 public void setSelect(Point p, boolean b) { 1189 1190 //如果是拖动,则要优化一下,以提高效率 1191 1192 if (b) { 1193 1194 //表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和 1195 1196 //将要显示的标签找到了就可以了 1197 1198 boolean findPrevious = false, findNext = false; 1199 1200 for (MyLabel m : list) { 1201 1202 if (m.contains(p)) { 1203 1204 findNext = true; 1205 1206 if (m.getIsSelected()) { 1207 1208 findPrevious = true; 1209 1210 } else { 1211 1212 m.setSelected(true, b); 1213 1214 } 1215 1216 } else if (m.getIsSelected()) { 1217 1218 findPrevious = true; 1219 1220 m.setSelected(false, b); 1221 1222 } 1223 1224 if (findPrevious && findNext) { 1225 1226 return; 1227 1228 } 1229 1230 } 1231 1232 } else { 1233 1234 MyLabel temp = null; 1235 1236 for (MyLabel m : list) { 1237 1238 if (m.contains(p)) { 1239 1240 temp = m; 1241 1242 } else if (m.getIsSelected()) { 1243 1244 m.setSelected(false, b); 1245 1246 } 1247 1248 } 1249 1250 if (temp != null) { 1251 1252 temp.setSelected(true, b); 1253 1254 } 1255 1256 } 1257 1258 } 1259 1260 1261 1262 } 1263 1264 1265 1266 private class JP4 extends JPanel { 1267 1268 private static final long serialVersionUID = -6391305687575714469L; 1269 1270 1271 1272 public JP4() { 1273 1274 super(new BorderLayout()); 1275 1276 this.setPreferredSize(new Dimension(295, 20)); 1277 1278 this.setBackground(new Color(160, 185, 215)); 1279 1280 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); 1281 1282 final JLabel jl = new JLabel("今天: " + sdf.format(new Date())); 1283 1284 jl.setToolTipText("点击选择今天日期"); 1285 1286 this.add(jl, BorderLayout.CENTER); 1287 1288 jl.addMouseListener(new MouseAdapter() { 1289 1290 public void mouseEntered(MouseEvent me) { 1291 1292 jl.setCursor(new Cursor(Cursor.HAND_CURSOR)); 1293 1294 jl.setForeground(Color.RED); 1295 1296 } 1297 1298 1299 1300 public void mouseExited(MouseEvent me) { 1301 1302 jl.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 1303 1304 jl.setForeground(Color.BLACK); 1305 1306 } 1307 1308 1309 1310 public void mousePressed(MouseEvent me) { 1311 1312 jl.setForeground(Color.WHITE); 1313 1314 select.setTime(new Date()); 1315 1316 refresh(); 1317 1318 commit(); 1319 1320 } 1321 1322 1323 1324 public void mouseReleased(MouseEvent me) { 1325 1326 jl.setForeground(Color.BLACK); 1327 1328 } 1329 1330 }); 1331 1332 } 1333 1334 1335 1336 private void updateDate() { 1337 1338 1339 1340 } 1341 1342 } 1343 1344 1345 1346 public static void main(String[] args) { 1347 1348 DateChooser dateChooser1 = DateChooser.getInstance("yyyy-MM-dd"); 1349 1350 DateChooser dateChooser2 = DateChooser.getInstance("yyyy-MM-dd"); 1351 1352 JTextField showDate1 = new JTextField("单击选择日期"); 1353 1354 JLabel showDate2 = new JLabel("单击选择日期"); 1355 1356 1357 1358 dateChooser1.register(showDate1); 1359 1360 dateChooser2.register(showDate2); 1361 1362 1363 1364 JFrame jf = new JFrame("测试日期选择器"); 1365 1366 jf.add(showDate1, BorderLayout.NORTH); 1367 1368 jf.add(showDate2, BorderLayout.SOUTH); 1369 1370 jf.pack(); 1371 1372 jf.setLocationRelativeTo(null); 1373 1374 jf.setVisible(true); 1375 1376 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 1377 1378 } 1379 }
时间: 2024-10-07 03:33:38