下面是我用SWT写的一个日历控件,主要是用于让用记选择日期,可以通过按钮 上一年、下一年、上一月 和 下一月 调整到要切换的月份,也可以通过改 年 和 月 的下拉框中的选择项来切换到指定年月,还可以直接在 年 和 月 的下拉框中输入要切换到的年月后按 回车键 切换到指定年月。运行后的效果如下图所示:
源代码如下:
- package com.hmw.tools;
- import java.util.Calendar;
- import org.eclipse.swt.SWT;
- import org.eclipse.swt.custom.CLabel;
- import org.eclipse.swt.events.KeyAdapter;
- import org.eclipse.swt.events.KeyEvent;
- import org.eclipse.swt.events.KeyListener;
- import org.eclipse.swt.events.MouseAdapter;
- import org.eclipse.swt.events.MouseEvent;
- import org.eclipse.swt.events.MouseListener;
- import org.eclipse.swt.events.SelectionAdapter;
- import org.eclipse.swt.events.SelectionEvent;
- import org.eclipse.swt.events.SelectionListener;
- import org.eclipse.swt.graphics.Color;
- import org.eclipse.swt.graphics.Rectangle;
- import org.eclipse.swt.layout.GridData;
- import org.eclipse.swt.layout.GridLayout;
- import org.eclipse.swt.widgets.Button;
- import org.eclipse.swt.widgets.Combo;
- import org.eclipse.swt.widgets.Display;
- import org.eclipse.swt.widgets.Shell;
- /**
- * 日历弹出窗口
- *
- * @author Carl He
- *
- */
- public class CalendarWidget{
- /** 显示对象 */
- private Display display = null;
- /** 窗口对象 */
- private Shell shell = null;
- /** 窗口的宽度 */
- private static final int SHELLWIDTH = 380;
- /** 窗口的高度 */
- private static final int SHELLHEIGHT = 280;
- /**Clabel大小的宽度*/
- private static final int GRIDDATAHINT = 20;
- /** 上一年 */
- private static final String TOOPTIPTEXT_PREVIOUSYEAR = "上一年";
- /** 下一年 */
- private static final String TOOPTIPTEXT_NEXTYEAR = "下一年";
- /** 上一月 */
- private static final String TOOPTIPTEXT_PREVIOUSMONTH = "上一月";
- /** 下一月 */
- private static final String TOOPTIPTEXT_NEXTMONTH = "下一月";
- /** 星期日 —— 星期六 */
- private static final String[] weekdays = { "星期日", "星期一", "星期二", "星期三",
- "星期四", "星期五", "星期六" };
- /**年下拉框显示到当前年的前后多少年*/
- private static final int halfYearItemCount = 20;
- /**年份下拉框选项的数组*/
- private static final String[] years = new String[halfYearItemCount*2+1];
- /**月份:1 —— 12 */
- private static final String[] months = { "1", "2", "3", "4","5", "6", "7", "8", "9", "10","11", "12",};
- /**选择的日期:yyyy-MM-dd*/
- private String selectedDate="";
- /**年的下拉框*/
- Combo cbo_year;
- /**月的下拉框*/
- Combo cbo_month;
- /**显示日的Clable数组*/
- private final CLabel[] clbl_days = new CLabel[42]; // 6 * 7
- /** 日历窗体的背景颜色*/
- private Color COLOR_SHELL_BACKGROUND = null;
- /** 星期X标签的背景颜色*/
- private Color COLOR_CLBLWEEKDAY_BACKGROUND = null;
- /** 白色(得到的为系统的颜色,不需要对其进行资源释放)*/
- private Color COLOR_SYSTEM_WHITE = null;
- /** 蓝色(得到的为系统的颜色,不需要对其进行资源释放)*/
- private Color COLOR_SYSTEM_BLUE = null;
- public CalendarWidget(Shell parent) {
- Rectangle parentRec = parent.getBounds();
- display = parent.getDisplay();
- COLOR_SHELL_BACKGROUND = new Color(display,219, 235, 250);
- COLOR_CLBLWEEKDAY_BACKGROUND = new Color(display, 64, 128, 128);
- COLOR_SYSTEM_WHITE = display.getSystemColor(SWT.COLOR_WHITE);
- COLOR_SYSTEM_BLUE = display.getSystemColor(SWT.COLOR_BLUE);
- shell = new Shell(parent, SWT.CLOSE | SWT.APPLICATION_MODAL);
- shell.setText("选择日期");
- // 保证显示在父窗体的正中间
- shell.setBounds(parentRec.x + (parentRec.width - SHELLWIDTH) / 2,
- parentRec.y + (parentRec.height - SHELLHEIGHT) / 2, SHELLWIDTH,
- SHELLHEIGHT);
- GridLayout gridLayout = new GridLayout();
- gridLayout.numColumns = 7;
- gridLayout.makeColumnsEqualWidth = true;
- shell.setLayout(gridLayout);
- shell.setBackground(COLOR_SHELL_BACKGROUND);
- // 上一年
- Button btn_yearPrevious = new Button(shell, SWT.ARROW | SWT.UP);
- btn_yearPrevious.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- btn_yearPrevious.setToolTipText(TOOPTIPTEXT_PREVIOUSYEAR);
- btn_yearPrevious.addSelectionListener(btnSelectionListener);
- // 上一月
- Button btn_monthPrevious = new Button(shell, SWT.ARROW | SWT.LEFT);
- btn_monthPrevious.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- btn_monthPrevious.setToolTipText(TOOPTIPTEXT_PREVIOUSMONTH);
- btn_monthPrevious.addSelectionListener(btnSelectionListener);
- cbo_year = new Combo(shell, SWT.DROP_DOWN);
- cbo_year.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- cbo_year.addSelectionListener(cboSelectionListener);
- cbo_year.addKeyListener(cboKeyListener);
- CLabel clabel = new CLabel(shell, SWT.CENTER | SWT.SHADOW_OUT);
- clabel.setBackground(COLOR_SYSTEM_WHITE);
- clabel.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- clabel.setText("-");
- cbo_month = new Combo(shell, SWT.DROP_DOWN);
- cbo_month.setItems(months);
- cbo_month.select(Calendar.getInstance().get(Calendar.MONTH));
- cbo_month.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- cbo_month.addSelectionListener(cboSelectionListener);
- cbo_month.addKeyListener(cboKeyListener);
- // 下一月
- Button btn_monthNext = new Button(shell, SWT.ARROW | SWT.RIGHT);
- btn_monthNext.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- btn_monthNext.setToolTipText(TOOPTIPTEXT_NEXTMONTH);
- btn_monthNext.addSelectionListener(btnSelectionListener);
- // 下一年
- Button btn_yearNext = new Button(shell, SWT.ARROW | SWT.DOWN);
- btn_yearNext.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
- btn_yearNext.setToolTipText(TOOPTIPTEXT_NEXTYEAR);
- btn_yearNext.addSelectionListener(btnSelectionListener);
- GridData gridData_1 = null;
- // 将 星期日 —— 星期六 的标签显示出来
- for (int i = 0; i < weekdays.length; i++) {
- CLabel clbl_weekDay = new CLabel(shell, SWT.CENTER | SWT.SHADOW_OUT);
- clbl_weekDay.setForeground(COLOR_SYSTEM_WHITE);
- clbl_weekDay.setBackground(COLOR_CLBLWEEKDAY_BACKGROUND);
- gridData_1 = new GridData(SWT.FILL,SWT.CENTER,true,false);
- gridData_1.widthHint = GRIDDATAHINT;
- gridData_1.heightHint = GRIDDATAHINT;
- clbl_weekDay.setLayoutData(gridData_1);
- clbl_weekDay.setText(weekdays[i]);
- }
- // 将当月的所有 日 的标签显示出来
- for (int i = 0; i < clbl_days.length; i++) {
- clbl_days[i] = new CLabel(shell, SWT.FLAT | SWT.CENTER);
- clbl_days[i].setLayoutData(new GridData(GridData.FILL_HORIZONTAL
- | GridData.FILL_VERTICAL));
- clbl_days[i].setCursor(display.getSystemCursor(SWT.CURSOR_HAND));
- clbl_days[i].addMouseListener(clblMouseListener);
- }
- }
- /**
- * 给年的下拉框设置设置选项
- * @param middleYear 中间年份
- */
- private void setCboYearItems(int middleYear){
- int selectIndex = halfYearItemCount;
- //确保不出现负的年份
- if(middleYear < halfYearItemCount){
- selectIndex = middleYear;
- middleYear = halfYearItemCount;
- }
- int index = 0;
- for (int i = middleYear-halfYearItemCount; i <= middleYear+halfYearItemCount; i++) {
- years[index++] = ""+i;
- }
- cbo_year.setItems(years);
- cbo_year.select(selectIndex);
- }
- /**
- * 得到指定年月的天数
- *
- * @param year
- * 年
- * @param month
- * 月(1-12)
- * @return 指定年月的天数,如:year=2008,month=1 就返回 2008年1月的天数:31
- */
- private int getDayCountOfMonth(int year, int month) {
- Calendar cal = Calendar.getInstance();
- cal.set(year, month - 1, 1); // 因为 Calendar中的 month 是 0-11,故month要减去1
- Calendar cal2 = (Calendar) cal.clone();
- cal2.add(Calendar.MONTH, 1);
- cal2.add(Calendar.DAY_OF_MONTH, -1);
- return cal2.get(Calendar.DAY_OF_MONTH);
- }
- /**
- * 得到下拉框中的年和月
- */
- private int[] getYearAndMonth(){
- Calendar now = Calendar.getInstance();
- int year = now.get(Calendar.YEAR); //年
- int month = now.get(Calendar.MONTH)+1; //月
- if("".equals(cbo_year.getText().trim()))
- cbo_year.setText(year+"");
- else{
- try {
- year = Integer.parseInt(cbo_year.getText().trim());
- } catch (NumberFormatException e) {
- //年 下拉框中的文本不是一个Int型数字,则设为当前年
- cbo_year.setText(year+"");
- }
- }
- if("".equals(cbo_month.getText().trim()))
- cbo_month.setText(month+"");
- else{
- try {
- month = Integer.parseInt(cbo_month.getText().trim());
- if(month<1){
- month = 1;
- cbo_month.setText("1");
- }else if(month>12){
- month = 12;
- cbo_month.setText("12");
- }
- } catch (NumberFormatException e) {
- // 月 下拉框中的文本不是一个Int型数字,则设为当前月
- cbo_month.setText(month+"");
- }
- }
- return new int[]{year, month};
- }
- /**
- * 为所有的 日 标签设置相关属性
- * @param reflushCboYearItems 是否刷新年下拉框中的选项
- */
- private void displayClblDays(boolean reflushCboYearItems) {
- Calendar calendar = Calendar.getInstance();
- int currentDate = calendar.get(Calendar.DATE); // 日
- int[] yearAndMonth = getYearAndMonth();
- int year = yearAndMonth[0]; //年
- int month = yearAndMonth[1]; //月
- calendar.set(year,month-1,1); //Calendar中的month为0-11,故在此处month要减去1
- int beginIndex = calendar.get(Calendar.DAY_OF_WEEK) - 1; //得到指定月份的第一天为星期几,Calendar对象返回的1-7对应星期日-星期六,故减去1
- int endIndex = beginIndex + getDayCountOfMonth(year, month) - 1;
- if(reflushCboYearItems)
- setCboYearItems(year);
- int day=1;
- for (int i = 0; i < clbl_days.length; i++) {
- if (i >= beginIndex && i <= endIndex) {
- clbl_days[i].setText(day + "");
- clbl_days[i].setToolTipText(year + "-" + month+"-"+day);
- if (day == currentDate)
- clbl_days[i].setBackground(COLOR_SYSTEM_BLUE);
- else
- clbl_days[i].setBackground(COLOR_SYSTEM_WHITE);
- day++;
- } else {
- clbl_days[i].setText("");
- clbl_days[i].setToolTipText("");
- clbl_days[i].setBackground(COLOR_SYSTEM_WHITE);
- }
- }
- }
- public String open() {
- displayClblDays(true);
- shell.open();
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
- COLOR_SHELL_BACKGROUND.dispose();
- COLOR_CLBLWEEKDAY_BACKGROUND.dispose();
- return selectedDate;
- }
- private MouseListener clblMouseListener = new MouseAdapter() {
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.swt.events.MouseAdapter#mouseDown(org.eclipse.swt.events.MouseEvent)
- */
- @Override
- public void mouseDown(MouseEvent e) {
- selectedDate = ((CLabel) e.widget).getToolTipText();
- if (!"".equals(selectedDate))
- shell.close();
- }
- };
- private SelectionListener btnSelectionListener = new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- String tooptip = ((Button)e.widget).getToolTipText();
- int[] yearAndMonth = getYearAndMonth();
- int year = yearAndMonth[0];
- int month = yearAndMonth[1];
- boolean reflushCboyearItems = true;
- //前一年
- if(TOOPTIPTEXT_PREVIOUSYEAR.equals(tooptip))
- cbo_year.setText((year-1)+"" );
- //后一年
- else if(TOOPTIPTEXT_NEXTYEAR.equals(tooptip))
- cbo_year.setText((year+1)+"" );
- //前一月
- else if(TOOPTIPTEXT_PREVIOUSMONTH.equals(tooptip)){
- if(month == 1){
- setCboYearItems(year-1 );
- cbo_month.select(11);
- }else{
- cbo_month.select(month-2);
- reflushCboyearItems = false;
- }
- //后一月
- }else if(TOOPTIPTEXT_NEXTMONTH.equals(tooptip)){
- if(month == 12){
- setCboYearItems(year+1 );
- cbo_month.select(0);
- }else{
- cbo_month.select(month);
- reflushCboyearItems = false;
- }
- }
- displayClblDays(reflushCboyearItems);
- }
- };
- private SelectionListener cboSelectionListener = new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- boolean reflushCboyearItems = e.widget == cbo_year ? true : false;
- displayClblDays(reflushCboyearItems);
- }
- };
- private KeyListener cboKeyListener = new KeyAdapter(){
- /* (non-Javadoc)
- * @see org.eclipse.swt.events.KeyAdapter#keyPressed(org.eclipse.swt.events.KeyEvent)
- */
- @Override
- public void keyPressed(KeyEvent event) {
- //小键盘的Enter或Enter,显示日历
- if (event.keyCode == 16777296 || event.keyCode == 13) {
- boolean reflushCboyearItems = event.widget == cbo_year ? true : false;
- displayClblDays(reflushCboyearItems);
- }else{
- //只能输入数字
- if((event.keyCode<'0' || event.keyCode >'9') && !(event.keyCode == SWT.BS || event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN))
- event.doit = false;
- }
- }
- };
- public static void main(String args[]) {
- try {
- Display display = Display.getDefault();
- Shell shell = new Shell(display, SWT.SHELL_TRIM);
- shell.setSize(500, 375);
- shell.open();
- shell.layout();
- CalendarWidget ca = new CalendarWidget(shell);
- System.out.println(ca.open());
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch())
- display.sleep();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }