1. 免费日期选择控件DatePicker
DatePicker它是一个下拉列表框, 提供了日期选择的功能.但是这个组件有日期对应星期几显示错误的bug。 官方主页: http://sourceforge.net/projects/swt-datepicker/ 本人对其进行了修补,源代码如下: /** * 开源免费免费日期选择控件(修订版) * 来自:http://sourceforge.net/projects/swt-datepicker/ */ package test; import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.Date; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; 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.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TypedListener; import com.swtdesigner.SWTResourceManager; /** * The date picker panel * * changes by sebthom ~ setDate will fire the Selection event + you can use * setDate(null) to clear the selection, the calendar will display the current * date, but getDate will return null until the user explicitely selects a date * from the control * * @author 廖龙龙(修订) * @since 2008.12.9 */ public class DatePicker extends Composite { // ~ Inner Classes // ---------------------------------------------------------- private class DatePanel extends Canvas { // ~ Instance fields(实例域) // ---------------------------------------------------- private int colSize;// 列宽 private Display display = Display.getCurrent(); private int rowSize;// 行高 private Calendar temp = Calendar.getInstance(); // 构造方法 /** * 使用GC绘图类实现日历面板 */ public DatePanel(Composite parent, int style) { super(parent, style | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE); GC gc = new GC(this); Point p = gc.stringExtent("Q"); gc.dispose(); colSize = p.x * 3;// 列宽 rowSize = (int) (p.y * 1.3);// 行高 addPaintListener(new PaintListener() { public void paintControl(PaintEvent event) { onPaint(event); } }); addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { redraw(); } }); addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { onKeyDown(e); } }); addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent e) { doubleClick(); } public void mouseDown(MouseEvent e) { onMouseDown(e); } }); addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent e) { onMouseMove(e); } }); } /** * 根据星期几的位置顺序赋值,源代码这里有误 */ private int computeOffset(int day) { switch (day) { case Calendar.MONDAY: return 2; case Calendar.TUESDAY: return 3; case Calendar.WEDNESDAY: return 4; case Calendar.THURSDAY: return 5; case Calendar.FRIDAY: return 6; case Calendar.SATURDAY: return 7; case Calendar.SUNDAY: return 1; } return -1; } public Point computeSize(int wHint, int hHint, boolean changed) { return new Point(colSize * 7, rowSize * 7); } /** * Method drawTextImage. * * @param gc * @param string * @param object * @param i * @param i1 * @param i2 * @param colSize * @param rowSize */ private void drawTextImage(GC gc, String string, int x, int y, int colSize, int rowSize) { gc.fillRectangle(x, y, colSize, rowSize); gc.drawString(string, x, y, true); } private int getDayFromPoint(int x, int y) { int result = -1; for (int i = 1; i <= 31; i++) { Point p = getDayPoint(i); Rectangle r = new Rectangle(p.x, p.y, colSize, rowSize); if (r.contains(x, y)) { result = i; break; } } return result; } /** * 设置星期几的标题样式 */ private String getDayName(int day) { String weekdstr = dateSymbols.getShortWeekdays()[day]; int weekindex = weekdstr.indexOf("星期"); if (weekindex != -1) { weekdstr = weekdstr.substring(2); } return weekdstr; } /** * 获取当前日期在表格中的位置坐标 */ private Point getDayPoint(int day) { syncTime(); temp.set(Calendar.DAY_OF_MONTH, 1); int firstDayOffset = computeOffset(temp.get(Calendar.DAY_OF_WEEK)) - 1; temp.set(Calendar.DAY_OF_MONTH, day); int dayOffset = computeOffset(temp.get(Calendar.DAY_OF_WEEK)); int x = (dayOffset - 1) * colSize; // 设置首行日期数字开始显示的Y坐标 int y = (1 + (((firstDayOffset + day) - 1) / 7)) * rowSize + 4; return new Point(x, y); } private int getMaxDay() { syncTime(); int day = 28; for (int i = 0; i < 10; i++) { temp.set(Calendar.DAY_OF_MONTH, day); if (temp.get(Calendar.MONTH) != cal.get(Calendar.MONTH)) { return day - 1; } day++; } return -1; } private void onKeyDown(KeyEvent e) { if (e.character == SWT.ESC) { dateSelected(false); return; } if ((e.character == ' ') || (e.character == '/r')) { dateSelected(true); return; } int day = cal.get(Calendar.DAY_OF_MONTH); int month = cal.get(Calendar.MONTH); int oldDay = day; int oldMonth = month; if (e.keyCode == SWT.ARROW_LEFT) { day--; } if (e.keyCode == SWT.ARROW_RIGHT) { day++; } if (e.keyCode == SWT.ARROW_UP) { day = ((day - 7) < 1 ? oldDay : day - 7); } if (e.keyCode == SWT.ARROW_DOWN) { day = ((day + 7) > getMaxDay() ? oldDay : day + 7); } if (e.keyCode == SWT.PAGE_UP) { month--; } if (e.keyCode == SWT.PAGE_DOWN) { month++; } cal.set(Calendar.MONTH, month); cal.set(Calendar.DAY_OF_MONTH, day); if ((day != oldDay) || (month != oldMonth)) { redraw(); if (month != oldMonth) { updateMonthLabel(); } } } private void onMouseDown(MouseEvent e) { int day = getDayFromPoint(e.x, e.y); if (day > 0) { cal.set(Calendar.DAY_OF_MONTH, day); dateSelected(true); updateDate(); } } private void onMouseMove(MouseEvent e) { int day = getDayFromPoint(e.x, e.y); selection = day; updateDate(); } /** * 绘制日期显示面板及其相应的日期数值 */ private void onPaint(PaintEvent event) { Rectangle rect = getClientArea(); GC gc0 = event.gc; Image image = new Image(display, rect.width, rect.height); GC gc = new GC(image); gc.setBackground(display .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); gc.fillRectangle(rect); // 绘制面板的标题,显示星期几信息 int x = 0; int y = 1; for (int i = 0; i < 7; i++) { // 将表头中星期六这一格显示为红色 // if (i == 6) { // gc.setForeground(display.getSystemColor(SWT.COLOR_RED)); // } gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE)); drawTextImage(gc, getDayName(1 + i), x, 3, colSize, rowSize); x += colSize; } gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); y += rowSize; // 使用默认的前景色绘制星期几上下的直线 gc.drawLine(0, 0 + 1, rect.width, 0 + 1); gc.drawLine(0, y - 1, rect.width, y - 1); // 在日期的最后画一条直线 // gc.drawLine(0, y +rowSize*6, rect.width, y + rowSize*6); syncTime(); int day = 1; while (true) { temp.set(Calendar.DAY_OF_MONTH, day); if (temp.get(Calendar.MONTH) != cal.get(Calendar.MONTH)) { break; } // 判断给定的日期是星期几 // int dayOffset = computeOffset(temp.get(Calendar.DAY_OF_WEEK)); Point p = getDayPoint(day); // 根据当前系统的颜色设置日历面板的颜色 if (day == cal.get(Calendar.DAY_OF_MONTH)) { gc.setForeground(display .getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); gc.setBackground(display .getSystemColor(SWT.COLOR_LIST_SELECTION)); } else if (day == selection) { gc.setForeground(display .getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); } else { gc.setBackground(display .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); // 如果是星期六的日期就显示为红色 // gc.setForeground(display // .getSystemColor(dayOffset == 7 ? SWT.COLOR_RED // : SWT.COLOR_BLACK)); gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); } drawTextImage(gc, "" + day, p.x, p.y, colSize, rowSize); day++; } gc0.drawImage(image, 0, 0); gc.dispose(); image.dispose(); } private void syncTime() { temp.setTimeInMillis(cal.getTimeInMillis()); } } // ~ Instance fields // -------------------------------------------------------- private Calendar cal = Calendar.getInstance(); // sebthom private Date selectedDate; private DatePanel datePanel; private DateFormatSymbols dateSymbols = new DateFormatSymbols(); private Label monthLabel; private int selection = -1; // ~ Constructors // ----------------------------------------------------------- public DatePicker(Composite parent, int style) { super(parent, style); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 5; gridLayout.verticalSpacing = gridLayout.horizontalSpacing = 0; gridLayout.marginHeight = gridLayout.marginWidth = 0; setBackground(SWTResourceManager.getColor(255, 255, 255)); setLayout(gridLayout); GridData gridData; // previous year Button prevYear = new Button(this, SWT.FLAT); prevYear.setToolTipText("上一年"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gridData.heightHint = gridData.widthHint = 19; prevYear.setLayoutData(gridData); prevYear.setText("<<"); prevYear.setSelection(false); prevYear.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { cal.roll(Calendar.YEAR, -1); updateDate(); } }); // previous month Button prevMonth = new Button(this, SWT.FLAT); prevMonth.setToolTipText("上一月"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gridData.heightHint = gridData.widthHint = 19; prevMonth.setLayoutData(gridData); prevMonth.setText("<"); prevMonth.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { cal.roll(Calendar.MONTH, -1); updateDate(); } }); // current month monthLabel = new Label(this, SWT.CENTER); monthLabel.setToolTipText("选择的日期"); gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.CENTER); gridData.heightHint = prevYear.computeSize(19, 19).y; gridData.grabExcessHorizontalSpace = true; monthLabel.setLayoutData(gridData); // next month Button nextMonth = new Button(this, SWT.FLAT); nextMonth.setToolTipText("下一月"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.heightHint = gridData.widthHint = 19; nextMonth.setLayoutData(gridData); nextMonth.setText(">"); nextMonth.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { cal.roll(Calendar.MONTH, 1); updateDate(); } }); // next year Button nextYear = new Button(this, SWT.FLAT); nextYear.setToolTipText("下一年"); gridData = new GridData(GridData.HORIZONTAL_ALIGN_END); gridData.heightHint = gridData.widthHint = 19; nextYear.setLayoutData(gridData); nextYear.setText(">>"); nextYear.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { cal.roll(Calendar.YEAR, 1); updateDate(); } }); // a panel datePanel = new DatePanel(this, SWT.NONE); gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gridData.horizontalSpan = 5; datePanel.setLayoutData(gridData); updateDate(); } // ~ Methods // ---------------------------------------------------------------- public void addSelectionListener(SelectionListener listener) { checkWidget(); if (listener == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.Selection, typedListener); addListener(SWT.DefaultSelection, typedListener); } public Point computeSize(int wHint, int hHint, boolean changed) { Point pSize = datePanel.computeSize(wHint, hHint, changed); Point labelSize = monthLabel.computeSize(wHint, hHint, changed); int x = (pSize.x < (labelSize.x + 80) ? labelSize.x + 80 : pSize.x); int y = (pSize.y < (labelSize.y + 20) ? labelSize.y + 20 : pSize.y); return new Point(x, y); } private void dateSelected(boolean good) { // sebthom if (good) selectedDate = cal.getTime(); Event event = new Event(); event.doit = good; notifyListeners(SWT.Selection, event); } private void doubleClick() { Event event = new Event(); event.doit = true; notifyListeners(SWT.MouseDoubleClick, event); } private String getCurrentMonthName() { StringBuffer sb = new StringBuffer(); sb.append(cal.get(Calendar.YEAR)); sb.append("年"); sb.append(getMonthName(cal.get(Calendar.MONTH))); sb.append("月"); return sb.toString(); } /** * 获取当前选择的日期 */ public Date getDate() { return selectedDate; } /** * 设置中文缩减式日期显示 (1)十二月、十一月 (2)12月、11月 */ private String getMonthName(int month) { // 设置月份显示样式为如十二月、十一月 // String monname = dateSymbols.getShortMonths()[month]; // System.out.println(month); // int endindex = monname.indexOf("月"); // if (endindex != -1) { // monname = monname.substring(0, endindex); // } // 设置月份显示样式为如12月、11月 String monname = String.valueOf(month + 1); return monname; } public void removeSelectionListener(SelectionListener listener) { checkWidget(); if (listener == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.Selection, listener); removeListener(SWT.DefaultSelection, listener); } public void reset() { cal = Calendar.getInstance(); updateDate(); } /** * 初始化时,显示当前日期 */ public void setDate(Date date) { // sebthom // cal.setTime(date); selectedDate = date; cal.setTime(selectedDate == null ? new Date() : date); updateMonthLabel(); redraw(); } private void updateDate() { datePanel.redraw(); updateMonthLabel(); } private void updateMonthLabel() { monthLabel.setText(getCurrentMonthName()); } } |