package cn.edu.hactcm;
import java.awt.basicstroke;
import java.awt.borderlayout;
import java.awt.color;
import java.awt.component;
import java.awt.cursor;
import java.awt.dimension;
import java.awt.font;
import java.awt.graphics;
import java.awt.graphics2d;
import java.awt.gridlayout;
import java.awt.point;
import java.awt.polygon;
import java.awt.stroke;
import java.awt.toolkit;
import java.awt.event.focusevent;
import java.awt.event.focuslistener;
import java.awt.event.mouseadapter;
import java.awt.event.mouseevent;
import java.awt.event.mouselistener;
import java.awt.event.mousemotionlistener;
import java.text.simpledateformat;
import java.util.arraylist;
import java.util.calendar;
import java.util.comparator;
import java.util.date;
import java.util.list;
import javax.swing.borderfactory;
import javax.swing.jbutton;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.jpanel;
import javax.swing.popup;
import javax.swing.popupfactory;
import javax.swing.swingutilities;
import javax.swing.event.ancestorevent;
import javax.swing.event.ancestorlistener;
/**
*
* @author hadeslee
*/
public class datechooser extends jpanel{
private date initdate;
private calendar now=calendar.getinstance();
private calendar select;
private jpanel monthpanel;//月历
private jp1 jp1;//四块面板,组成
private jp2 jp2;
private jp3 jp3;
private jp4 jp4;
private font font=new font("宋体",font.plain,12);
private final labelmanager lm=new labelmanager();
private jlabel showdate;//,toselect;
private simpledateformat sdf=new simpledateformat("yyyy年mm月dd日");
private boolean isshow=false;
private popup pop;
/**
* creates a new instance of datechooser
*/
public datechooser() {
this(new date());
}
public datechooser(date date){
initdate=date;
select=calendar.getinstance();
select.settime(initdate);
initpanel();
initlabel();
public void setenabled(boolean b){
super.setenabled(b);
showdate.setenabled(b);
*得到当前选择框的日期
public date getdate(){
return select.gettime();
//根据初始化的日期,初始化面板
private void initpanel(){
monthpanel=new jpanel(new borderlayout());
monthpanel.setborder(borderfactory.createlineborder(color.blue));
jpanel up=new jpanel(new borderlayout());
up.add(jp1=new jp1(),borderlayout.north);
up.add(jp2=new jp2(),borderlayout.center);
monthpanel.add(jp3=new jp3(),borderlayout.center);
monthpanel.add(up,borderlayout.north);
monthpanel.add(jp4=new jp4(),borderlayout.south);
this.addancestorlistener(new ancestorlistener(){
public void ancestoradded(ancestorevent event) {
}
public void ancestorremoved(ancestorevent event) {
//只要祖先组件一移动,马上就让popup消失
public void ancestormoved(ancestorevent event) {
hidepanel();
});
//初始化标签
private void initlabel(){
showdate=new jlabel(sdf.format(initdate));
showdate.setrequestfocusenabled(true);
showdate.addmouselistener(new mouseadapter(){
public void mousepressed(mouseevent me){
showdate.requestfocusinwindow();
// toselect=new jlabel(sdf.format(initdate));
// toselect.setborder(borderfactory.createlineborder(color.black));
// toselect.setrequestfocusenabled(true);
this.setbackground(color.white);
this.add(showdate,borderlayout.center);
// this.add(toselect,borderlayout.east);
this.setpreferredsize(new dimension(90,25));
this.setborder(borderfactory.createlineborder(color.gray));
public void mouseentered(mouseevent me){
if(showdate.isenabled()){
showdate.setcursor(new cursor(cursor.hand_cursor));
showdate.setforeground(color.red);
}
public void mouseexited(mouseevent me){
showdate.setcursor(new cursor(cursor.default_cursor));
showdate.setforeground(color.black);
showdate.setforeground(color.cyan);
if(isshow){
hidepanel();
}else{
showpanel(showdate);
}
public void mousereleased(mouseevent me){
showdate.addfocuslistener(new focuslistener(){
public void focuslost(focusevent e){
public void focusgained(focusevent e){
//根据新的日期刷新
private void refresh(){
jp1.updatedate();
jp3.updatedate();
swingutilities.updatecomponenttreeui(this);
//提交日期
private void commit(){
system.out.println("选中的日期是:"+sdf.format(select.gettime()));
showdate.settext(sdf.format(select.gettime()));
hidepanel();
private void hidepanel(){
if(pop!=null){
isshow=false;
pop.hide();
pop=null;
}
private void showpanel(component owner){
point show=new point(0,showdate.getheight());
swingutilities.convertpointtoscreen(show,showdate);
dimension size=toolkit.getdefaulttoolkit().getscreensize();
int x=show.x;
int y=show.y;
if(x<0){
x=0;
if(x>size.width-295){
x=size.width-295;
if(y<size.height-170){
}else{
y-=188;
pop=popupfactory.getsharedinstance().getpopup(owner,monthpanel,x,y);
pop.show();
isshow=true;
private class jp1 extends jpanel{
jlabel left,right,center;
public jp1(){
super(new borderlayout());
this.setbackground(new color(160,185,215));
initjp1();
private void initjp1(){
left=new jlabel(" << ",jlabel.center);
left.settooltiptext("上一月");
right=new jlabel(" >> ",jlabel.center);
right.settooltiptext("下一月");
left.setborder(borderfactory.createemptyborder(10,0,0,0));
right.setborder(borderfactory.createemptyborder(10,0,0,0));
center=new jlabel("",jlabel.center);
updatedate();
this.add(left,borderlayout.west);
this.add(center,borderlayout.center);
this.add(right,borderlayout.east);
this.setpreferredsize(new dimension(295,25));
left.addmouselistener(new mouseadapter(){
public void mouseentered(mouseevent me){
left.setcursor(new cursor(cursor.hand_cursor));
left.setforeground(color.red);
public void mouseexited(mouseevent me){
left.setcursor(new cursor(cursor.default_cursor));
left.setforeground(color.black);
public void mousepressed(mouseevent me){
select.add(calendar.month,-1);
left.setforeground(color.white);
refresh();
public void mousereleased(mouseevent me){
});
right.addmouselistener(new mouseadapter(){
right.setcursor(new cursor(cursor.hand_cursor));
right.setforeground(color.red);
right.setcursor(new cursor(cursor.default_cursor));
right.setforeground(color.black);
select.add(calendar.month,1);
right.setforeground(color.white);
private void updatedate(){
center.settext(select.get(calendar.year)+"年"+(select.get(calendar.month)+1)+"月");
private class jp2 extends jpanel{
public jp2(){
this.setpreferredsize(new dimension(295,20));
protected void paintcomponent(graphics g){
g.setfont(font);
g.drawstring("星期日 星期一 星期二 星期三 星期四 星期五 星期六",5,10);
g.drawline(0,15,getwidth(),15);
private class jp3 extends jpanel{
public jp3(){
super(new gridlayout(6,7));
this.setpreferredsize(new dimension(295,100));
initjp3();
private void initjp3(){
public void updatedate(){
this.removeall();
lm.clear();
date temp=select.gettime();
calendar select=calendar.getinstance();
select.settime(temp);
select.set(calendar.day_of_month,1);
int index=select.get(calendar.day_of_week);
int sum=(index==1?8:index);
select.add(calendar.day_of_month,0-sum);
for(int i=0;i<42;i++){
select.add(calendar.day_of_month,1);
lm.addlabel(new mylabel(select.get(calendar.year),
select.get(calendar.month),select.get(calendar.day_of_month)));
for(mylabel my:lm.getlabels()){
this.add(my);
private class mylabel extends jlabel implements comparator<mylabel>,
mouselistener,mousemotionlistener{
private int year,month,day;
private boolean isselected;
public mylabel(int year,int month,int day){
super(""+day,jlabel.center);
this.year=year;
this.day=day;
this.month=month;
this.addmouselistener(this);
this.addmousemotionlistener(this);
this.setfont(font);
if(month==select.get(calendar.month)){
this.setforeground(color.black);
}else{
this.setforeground(color.light_gray);
if(day==select.get(calendar.day_of_month)){
this.setbackground(new color(160,185,215));
this.setbackground(color.white);
public boolean getisselected(){
return isselected;
public void setselected(boolean b,boolean isdrag){
isselected=b;
if(b&&!isdrag){
int temp=select.get(calendar.month);
select.set(year,month,day);
if(temp==month){
swingutilities.updatecomponenttreeui(jp3);
}else{
this.repaint();
if(day==select.get(calendar.day_of_month)&&
month==select.get(calendar.month)){
//如果当前日期是选择日期,则高亮显示
g.setcolor(new color(160,185,215));
g.fillrect(0,0,getwidth(),getheight());
if(year==now.get(calendar.year)&&
month==now.get(calendar.month)&&
day==now.get(calendar.day_of_month)){
//如果日期和当前日期一样,则用红框
graphics2d gd=(graphics2d)g;
gd.setcolor(color.red);
polygon p=new polygon();
p.addpoint(0,0);
p.addpoint(getwidth()-1,0);
p.addpoint(getwidth()-1,getheight()-1);
p.addpoint(0,getheight()-1);
gd.drawpolygon(p);
if(isselected){//如果被选中了就画出一个虚线框出来
stroke s=new basicstroke(1.0f,basicstroke.cap_square,
basicstroke.join_bevel,1.0f,new float[]{2.0f,2.0f},1.0f);
gd.setstroke(s);
gd.setcolor(color.black);
super.paintcomponent(g);
public boolean contains(point p){
return this.getbounds().contains(p);
private void update(){
repaint();
public void mouseclicked(mouseevent e) {
public void mousepressed(mouseevent e) {
isselected=true;
update();
public void mousereleased(mouseevent e) {
point p=swingutilities.convertpoint(this,e.getpoint(),jp3);
lm.setselect(p,false);
commit();
public void mouseentered(mouseevent e) {
public void mouseexited(mouseevent e) {
public void mousedragged(mouseevent e) {
lm.setselect(p,true);
public void mousemoved(mouseevent e) {
public int compare(mylabel o1, mylabel o2) {
calendar c1=calendar.getinstance();
c1.set(o1.year,o2.month,o1.day);
calendar c2=calendar.getinstance();
c2.set(o2.year,o2.month,o2.day);
return c1.compareto(c2);
private class labelmanager{
private list<mylabel> list;
public labelmanager(){
list=new arraylist<mylabel>();
public list<mylabel> getlabels(){
return list;
public void addlabel(mylabel my){
list.add(my);
public void clear(){
list.clear();
public void setselect(mylabel my,boolean b){
for(mylabel m:list){
if(m.equals(my)){
m.setselected(true,b);
m.setselected(false,b);
public void setselect(point p,boolean b){
//如果是拖动,则要优化一下,以提高效率
if(b){
//表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和
//将要显示的标签找到了就可以了
boolean findprevious=false,findnext=false;
for(mylabel m:list){
if(m.contains(p)){
findnext=true;
if(m.getisselected()){
findprevious=true;
}else{
m.setselected(true,b);
}
}else if(m.getisselected()){
findprevious=true;
m.setselected(false,b);
if(findprevious&&findnext){
return;
mylabel temp=null;
temp=m;
if(temp!=null){
temp.setselected(true,b);
private class jp4 extends jpanel{
public jp4(){
simpledateformat sdf=new simpledateformat("yyyy年mm月dd日");
final jlabel jl=new jlabel("今天: "+sdf.format(new date()));
jl.settooltiptext("点击回到今天日期");
this.add(jl,borderlayout.center);
jl.addmouselistener(new mouseadapter(){
jl.setcursor(new cursor(cursor.hand_cursor));
jl.setforeground(color.red);
jl.setcursor(new cursor(cursor.default_cursor));
jl.setforeground(color.black);
jl.setforeground(color.white);
select.settime(new date());
commit();
public static void main(string[] args) {
final datechooser mp=new datechooser();
jframe jf=new jframe("test");
jf.add(mp,borderlayout.center);
jf.add(new jbutton("测试用的"),borderlayout.north);
jf.pack();
jf.setlocationrelativeto(null);
jf.setvisible(true);
jf.setdefaultcloseoperation(jframe.exit_on_close);
}