首先,新建一个Java工程,再新建一个类,类名为CalendarPanel ,继承JPanel,然后把一下的代码复制到这个类中。
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class CalendarPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private JLabel btn_lastYear = null;
private JLabel btn_nextYear = null;
private JLabel btn_lastMonth = null;
private JLabel btn_nextMonth = null;
private JLabel lb_datetime = null;
private JPanel panel_maincalenderpanel = null;
private JLabel lblNewLabel = null;
private JLabel label = null;
private JLabel label_1 = null;
private JLabel label_2 = null;
private JLabel label_3 = null;
private JLabel label_4 = null;
private JLabel label_5 = null;
private JLabel btn_close = null;
private JButton btn_today = null;
private JButton btn_cancel = null;
private Object component = null; //日历控件的载体组件,如TextField
private String returnDateStr = null; //保存选中的日期
private CallBack callBack = null;
private String patern = "yyyy-MM-dd"; //日期格式
private SimpleDateFormat sdf = null;
private String nowDatetime = null ; //当前系统日期字符串
/**
* 带参数的构造函数,该构造函数将构造一个设置了日历控件的载体组件的CalenderPanel对象实例
* @param component 日历控件的载体组件,可以是TextField、JTextField、Label、JLabel
* @param patern 日期格式 ,默认为yyyy-MM-dd
*/
public CalendarPanel(Object component,String patern) {
this(patern);
this.component = component;
}
/**
* 带参数的构造函数,该构造函数将构造一个CalenderPanel对象实例,该对象时候没有设置日历控件的载体组件
* * @param patern 日期格式,默认为yyyy-MM-dd
*/
public CalendarPanel(String patern) {
super();
//初始化日期格式化
this.patern = patern;
sdf = new SimpleDateFormat(patern);
nowDatetime = sdf.format(new Date());
setLayout(null);
//设置日历控件的整体主面板边框为灰色
this.setBorder(BorderFactory.createLineBorder(Color.gray));
//初始化日历控件上的各个组件
init();
//创建日历控件的日期部分面板
createCalendarPanel(nowDatetime);
}
/**
* 无参数的构造函数,该构造函数将构造一个CalenderPanel对象实例,该对象时候没有设置日历控件的载体组件
*/
public CalendarPanel() {
super();
//初始化日期格式化
sdf = new SimpleDateFormat(patern);
nowDatetime = sdf.format(new Date());
setLayout(null);
//设置日历控件的整体主面板边框为灰色
this.setBorder(BorderFactory.createLineBorder(Color.gray));
//初始化日历控件上的各个组件
init();
//创建日历控件的日期部分面板
createCalendarPanel(nowDatetime);
}
/**
* 获取日历控件的载体组件
* @return 返回该日历控件中的载体组件,如果没有设置,则返回null;
*/
public Object getComponent() {
return component;
}
/**
* 设置日历控件的载体组件
* @param component
*/
public void setComponent(Object component) {
this.component = component;
}
/**
* 获取选择日期时候的日期字符串
* @return
*/
public String getReturnDateStr() {
return returnDateStr;
}
/**
* 获取日历控件的回调接口对象
* @return
*/
public CallBack getCallBack() {
return callBack;
}
/**
* 设置日历控件的回调接口对象
* @param callBack
*/
public void setCallBack(CallBack callBack) {
this.callBack = callBack;
}
/**
* 创建下拉选择日历控件的主体面板(即显示日期部分的面板)
* @param date 需要显示的日期
*/
private void createCalendarPanel(String date){
//每次刷新日期显示,需要重新创建日期部分的面板
//如果日期部分的面板不为null,可以先将其remove,然后再创建
if(panel_maincalenderpanel!=null){
panel_maincalenderpanel.setVisible(false);
this.remove(panel_maincalenderpanel);
}
//创建新的日期部分的面板
panel_maincalenderpanel = new JPanel();
panel_maincalenderpanel.setBackground(Color.WHITE);
panel_maincalenderpanel.setBounds(2, 47, 247, 156);
panel_maincalenderpanel.setLayout(new GridLayout(6,7));
add(panel_maincalenderpanel);
Date today = null;
try {
today = sdf.parse(date);
} catch (ParseException e1) {
e1.printStackTrace();
return;
}
Calendar c = new GregorianCalendar();
//将给定日期设置为需要显示的日期
c.setTime(today);
//需要将日改成1号,因为我们需要获取给定日期的第一天是星期几
c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH), 1);
int firstDayInMonthOfWeek = c.get(Calendar.DAY_OF_WEEK); //给定日期的第一天是星期几
int daysOfMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH); //给定日期对应月份的天数
//首先生成给定日期第一天之前的空白部分
//例如:2011-11的第一天就是星期二,那么星期二之前的(星期日,星期一)我们不显示内容,需要生成空白
for(int i=1;i>");
btn_nextYear.setBounds(179, 0, 27, 23);
add(btn_nextYear);
btn_nextYear.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//改变日历控件面板的显示日期
changTheDate(Calendar.YEAR,true);
}
});
//上一月操作组件,这里使用一个JLabel
btn_lastMonth = new JLabel("<");
btn_lastMonth.setBounds(39, 0, 27, 23);
add(btn_lastMonth);
btn_lastMonth.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//改变日历控件面板的显示日期
changTheDate(Calendar.MONTH,false);
}
});
//下一月操作组件,这里使用一个JLabel
btn_nextMonth = new JLabel(">");
btn_nextMonth.setBounds(150, 0, 27, 23);
add(btn_nextMonth);
btn_nextMonth.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//改变日历控件面板的显示日期
changTheDate(Calendar.MONTH,true);
}
});
//显示日期的lable对象
lb_datetime = new JLabel("");
lb_datetime.setBounds(58, 2, 86, 19);
lb_datetime.setHorizontalAlignment(SwingConstants.CENTER);
add(lb_datetime);
lb_datetime.setText(nowDatetime);
lblNewLabel = new JLabel("日");
lblNewLabel.setForeground(Color.RED);
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel.setBounds(2, 22, 27, 23);
add(lblNewLabel);
label = new JLabel("一");
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setBounds(39, 22, 27, 23);
add(label);
label_1 = new JLabel("二");
label_1.setHorizontalAlignment(SwingConstants.CENTER);
label_1.setBounds(76, 22, 27, 23);
add(label_1);
label_2 = new JLabel("三");
label_2.setHorizontalAlignment(SwingConstants.CENTER);
label_2.setBounds(113, 22, 27, 23);
add(label_2);
label_3 = new JLabel("四");
label_3.setHorizontalAlignment(SwingConstants.CENTER);
label_3.setBounds(147, 22, 27, 23);
add(label_3);
label_4 = new JLabel("五");
label_4.setHorizontalAlignment(SwingConstants.CENTER);
label_4.setBounds(184, 22, 27, 23);
add(label_4);
label_5 = new JLabel("六");
label_5.setForeground(Color.GREEN);
label_5.setHorizontalAlignment(SwingConstants.CENTER);
label_5.setBounds(221, 22, 27, 23);
add(label_5);
btn_close = new JLabel("[X]");
btn_close.setBounds(222, 0, 27, 23);
btn_close.setForeground(Color.RED);
add(btn_close);
btn_close.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
CalendarPanel.this.setVisible(false);
}
});
//用于快速显示今天日期的按钮
btn_today = new JButton("今天");
btn_today.setBounds(10, 213, 60, 23);
btn_today.setContentAreaFilled(false);
btn_today.setBorder(BorderFactory.createLineBorder(Color.GRAY));
add(btn_today);
btn_today.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
createCalendarPanel(nowDatetime);
lb_datetime.setText(nowDatetime);
}
});
//用于取消日期选择的按钮
btn_cancel = new JButton("取消");
btn_cancel.setBounds(179, 213, 60, 23);
btn_cancel.setContentAreaFilled(false);
btn_cancel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
add(btn_cancel);
btn_cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CalendarPanel.this.setVisible(false);
}
});
}
/**
* 重新设置日历面板显示为系统当前日期
*/
public void reset(){
createCalendarPanel(nowDatetime);
lb_datetime.setText(nowDatetime);
}
/**
* 改变当前日历控件面板的日期显示
* @param YEAR_OR_MONTH 是对YEAR还是MONTH操作,这里需要传入Calendar类对应的常量值:Calendar.YEAR,Calendar.MONTH
* @param flag 对YEAR_OR_MONTH属性是进行加法操作还是减法操作,如果flag为true则是加法操作,否则为减法操作
*/
public void changTheDate(int YEAR_OR_MONTH,boolean flag){
String dateStr = lb_datetime.getText().trim();
Date date = null;
try {
date = sdf.parse(dateStr);
} catch (ParseException e1) {
e1.printStackTrace();
return;
}
Calendar c = Calendar.getInstance();
c.setTime(date);
if(flag){
//将对应的日期属性进行加法操作
c.set(YEAR_OR_MONTH,c.get(YEAR_OR_MONTH)+1 );
}else{
//将对应的日期属性进行减法操作
c.set(YEAR_OR_MONTH,c.get(YEAR_OR_MONTH)-1 );
}
date = c.getTime();
lb_datetime.setText(sdf.format(date));
createCalendarPanel(sdf.format(date));
}
public static void main(String[] args) {
Calendar c = new GregorianCalendar(2011,11,1);
System.out.println( c.get(Calendar.DAY_OF_WEEK));
}
public void initCalendarPanel(){
if(component instanceof javax.swing.JComponent){
JComponent j = (JComponent)component;
int w = j.getWidth();
int h = j.getHeight();
int x = j.getX();
int y = j.getY();
System.out.println("with:"+w +"height:"+h+"x:"+x+"y:"+y);
this.setComponent(component);
this.setBounds((x), y+h, 251, 245);
this.setVisible(false);
j.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (CalendarPanel.this.isVisible()){
CalendarPanel.this.setVisible(false);
}else{
CalendarPanel.this.setVisible(true);
CalendarPanel.this.reset();
}
}
});
}
}
}
/**
* 回调接口
* @author Administrator
*
*/
interface CallBack{
public void callback();
}
之后,在同一个包中再新建一个类名为DateChooser,继承JPanel。该类为测试类,测试上边CalendarPanel的实现是否成功。
import java.awt.Color;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
//测试类
public class DateChooser extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
//private static Point startp = null;
//private Point endp = null;
public static void main(String[] args) {
JFrame f = new JFrame();
f.setLayout(null);
JTextField txt1 = new JTextField();
JTextField txt2 = new JTextField();
txt1.setBounds(20, 50, 300, 30);
txt2.setBounds(20, 80, 300, 30);
// 定义日历控件面板类
CalendarPanel p = new CalendarPanel(txt1, "yyyy/MM/dd");
p.initCalendarPanel();
JLabel l = new JLabel("日历面板");
p.add(l);
f.getContentPane().add(p);
f.getContentPane().add(txt1);
f.getContentPane().add(txt2);
f.setSize(500, 400);
f.setBackground(Color.WHITE);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}