📄 calendarcanvas.java
字号:
//CalendarCanvas.java 实现日历画布 CalendarCanvas 类
package calendar;
import java.util.*;
import javax.microedition.lcdui.*;
public class CalendarCanvas extends Canvas implements CommandListener
{
//菜单命令,分别对应 下月,上月,下年,上年,选择当前日期
public static Command nextMonthCmd =new Command("NextMonth",Command.SCREEN,1);
public static Command prevMonthCmd =new Command("PrevMonth",Command.SCREEN,1);
public static Command nextYearCmd =new Command("NextYear",Command.SCREEN,1);
public static Command prevYearCmd =new Command("PrevYear",Command.SCREEN,1);
public static Command selectCmd =new Command("Select",Command.EXIT,2);
//周日到周六的文字
private static String weekDays= new String("SunMonTueWedThuFriSat");
//字体,用于显示正常的日期,假日,重要日期,含有重要事件的假日,可以根据需要修改
//考虑到性能的问题可以把字体对象的数量减少
private static Font[ ] fontShow={Font.getFont(Font.FACE_SYSTEM,Font.STYLE_PLAIN,Font.SIZE_SMALL),
Font.getFont(Font.FACE_SYSTEM,Font.STYLE_PLAIN,Font.SIZE_SMALL),
Font.getFont(Font.FACE_SYSTEM,Font.STYLE_UNDERLINED,Font.SIZE_SMALL),
Font.getFont(Font.FACE_SYSTEM,Font.STYLE_UNDERLINED|Font.STYLE_BOLD,Font.SIZE_SMALL)};
//颜色,用于显示不同类型日期的背景和字体颜色,可以根据需要修改
private static int[ ] clrBk= {0x00ffffff,0x00999999,0x00ffffff,0x00999999};
private static int[ ] clrFont={0x00000000,0x00000000,0x00000000,0x00000000};
//被选中的日期所使用的字体和颜色,可以根据需要修改
private static Font fontSelected=Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD,Font.SIZE_SMALL);
private static int clrSelectedBk=0x00cccccc, clrSelectedFont = 0x00000000;
//记录每月天数
private static int[ ] daysOfMonth={31,28,31,30,31,30,31,31,30,31,30,31};
//日期选择事件处理对象
protected DateSelectListener dateListener =null;
//重要日期判断对象
protected ImportDateFilter dateFilter = null;
//月份变动事件处理对象
protected MonthChangeListener monthListener =null;
private int width, height;//保存屏幕大小
private int startX;//保存绘图开始的X坐标位置,便于日历居中显示
private int iCellWidth,iCellHeight;//日历显示参数,每个日期所占空间
private Calendar calTemp;//日期对象
//当前焦点所在的日期
private int curYear, curMonth, curDay;
//构造器
public CalendarCanvas(Date date)
{
super();
//增加菜单
addCommand(selectCmd);
addCommand(nextMonthCmd);
addCommand(prevMonthCmd);
addCommand(nextYearCmd);
addCommand(prevYearCmd);
setCommandListener(this);
//设置当天的日期作为选中的日期
calTemp = Calendar.getInstance();
if(date != null)
calTemp.setTime(date);
curYear = calTemp.get(Calendar.YEAR);
curMonth = calTemp.get(Calendar.MONTH);
curDay = calTemp.get(Calendar.DAY_OF_MONTH);
//根据字体计算显示每个日期所需要高度和宽度
iCellWidth = fontSelected.substringWidth(weekDays, 0, 3)+2;
iCellHeight = fontSelected.getHeight()+2;
}
//设置重要日期判断对象
public void setImportDateFilter(ImportDateFilter filter)
{
dateFilter = filter;
}
//设置日期选择监听对象
public void setDateSelectListener(DateSelectListener listener)
{
dateListener = listener;
}
//设置月份变动监听对象
public void setMonthChangeListener(MonthChangeListener listener)
{
monthListener = listener;
}
//得到当前焦点所在的日期
public Calendar getFocusDate()
{
calTemp.set(Calendar.YEAR, curYear);
calTemp.set(Calendar.MONTH, curMonth);
calTemp.set(Calendar.DAY_OF_MONTH,1);
return calTemp;
}
//在画布显示前保存屏幕尺寸
protected void showNotify()
{
height = getHeight();
width = getWidth();
startX = (width- 7*iCellWidth)/2;
}
//绘制日历
protected void paint(Graphics g)
{
//填充屏幕
g.setColor(0x00ffffff);
g.fillRect(0,0,width,height);
//显示当前月的日历
paintMonth(g);
}
//处理按键事件
protected void keyPressed(int keyCode)
{
int newDay =curDay;
switch(getGameAction(keyCode))
{
case UP: //转到上一周
if(curDay>7)
newDay -=7;
break;
case DOWN: //转到下一周
if(curDay<=getDaysOfMonth(curYear, curMonth)-7)
newDay +=7;
break;
case LEFT: //转到上一天
if(curDay>1)
newDay --;
break;
case RIGHT: //转到下一天
if(curDay<getDaysOfMonth(curYear, curMonth) )
newDay ++;
break;
case FIRE: //确定选择某个日期
selectDate();
break;
}//当日期超出时没有切换到上个月或下个月
if(newDay != curDay)
{//日期改变后重绘界面
curDay = newDay;
repaint();
}
}
//处理指针事件
protected void pointerPressed(int x,int y)
{//判断指针所点击的位置所属于的日期
//第一步:判断是否在日期绘制的范围内
if(x<startX || x>=startX + iCellWidth*7)
return ;//不在绘制日期的范围内
if(y< iCellHeight*2)
return ;//不在绘制日期的范围内
//第二步:计算点击的日期是当月的第几天
calTemp.set(Calendar.YEAR, curYear);
calTemp.set(Calendar.MONTH, curMonth);
calTemp.set(Calendar.DAY_OF_MONTH,1);
int index =1;
index += ((y-iCellHeight*2)/iCellHeight) *7;
index += (x - startX)/iCellWidth;
index -= (calTemp.get(Calendar.DAY_OF_WEEK)-1);
//第三步:判断是否在当月日期范围内
int daysNum = getDaysOfMonth(curYear,curMonth); //得到当月的天数
if(index>0 && daysNum>= index)
{
curDay = index;
repaint();
}
}
//处理菜单命令事件
public void commandAction(Command c, Displayable d)
{
if(c == nextYearCmd)//切换到下一年
{
curYear ++;
curMonth=0;
notifyMonthChange();
}
else if(c == prevYearCmd)//切换到上一年
{
curYear --;
curMonth=11;
notifyMonthChange();
}
else if(c == nextMonthCmd)//切换到下一个月
nextMonth();
else if(c == prevMonthCmd)//切换到上一个月
prevMonth();
else if(c == selectCmd)
{//确定选择某个日期
selectDate();
}
repaint();
}
//绘制当前月的日历
protected void paintMonth(Graphics g)
{//绘制日历
//第一布,显示当前年月
int offsetY=0; //保存绘图的Y轴坐标
g.setColor(clrSelectedFont);
g.setFont(fontSelected);
g.drawString(curYear+" / "+(curMonth+1),startX+iCellWidth*7/2,offsetY+2,Graphics.HCENTER | Graphics.TOP);
//第二步,显示一周中每天的名称
g.setColor(clrSelectedFont);
g.setFont(fontSelected);
offsetY+=iCellHeight;
for(int i=0;i<7;i++)
g.drawSubstring(weekDays,i*3,3,startX+i*iCellWidth+1,offsetY,Graphics.LEFT|Graphics.TOP);
//第三步,显示当月所有日期
calTemp.set(Calendar.YEAR, curYear);
calTemp.set(Calendar.MONTH, curMonth);
int dayOW=0; //保存星期
int clr1,clr2; //保存颜色值
Font ft; //保存字体
int type =ImportDateFilter.NORMALDAY; //日期的类型
int daysNum = getDaysOfMonth(curYear,curMonth); //得到当月的天数
offsetY+=iCellHeight;
for(int i=1;i<=daysNum;i++)
{//分别对每天进行绘制
calTemp.set(Calendar.DAY_OF_MONTH,i);
dayOW = calTemp.get(Calendar.DAY_OF_WEEK); //得到当天是星期几
if(i==curDay)
{//当天是被选中的日期,用固定的字体和颜色进行显示
ft = fontSelected;
clr1 = clrSelectedBk;
clr2 = clrSelectedFont;
}
else
{//对于未选中的日期通过日期类型决定显示方式
if(dateFilter !=null)
{//判断当天是否重要日期
type =dateFilter.isImportantDate(calTemp);
}
//type = i %4;
ft = fontShow[type];
clr1 = clrBk[type];
clr2 = clrFont[type];
}
g.setFont(ft);
g.setColor(clr1);
g.fillRect(startX+(dayOW-1)*iCellWidth,offsetY,iCellWidth-1,iCellHeight-1);
g.setColor(clr2);
g.drawString(String.valueOf(i), startX+(dayOW-1)*iCellWidth+iCellWidth/2, offsetY+1, Graphics.HCENTER | Graphics.TOP);
if(dayOW ==Calendar.SATURDAY)
offsetY +=iCellHeight; // 转入下一周前增加Y轴坐标
}
}
//将月份改为下一个月
protected void nextMonth()
{
if(curMonth<11)
curMonth ++;
else
{
curMonth =0;
curYear ++;
}
curDay = 1;
notifyMonthChange();
}
//将月份改为上一个月
protected void prevMonth()
{
if(curMonth>0)
curMonth --;
else
{
curMonth =11;
curYear --;
}
curDay = 1;
notifyMonthChange();
}
//月份变化通知
protected void notifyMonthChange()
{
if(monthListener != null)
{
calTemp.set(Calendar.YEAR, curYear);
calTemp.set(Calendar.MONTH, curMonth);
calTemp.set(Calendar.DAY_OF_MONTH, curDay);
monthListener.monthChanged(this,calTemp);
}
}
//确定选择某个日期并引发事件
protected void selectDate()
{
if(dateListener != null)
{//引发事件
calTemp.set(Calendar.YEAR, curYear);
calTemp.set(Calendar.MONTH, curMonth);
calTemp.set(Calendar.DAY_OF_MONTH, curDay);
dateListener.dateSelected(this,calTemp);
}
}
//得到某年某个月的天数
protected int getDaysOfMonth(int year,int month)
{
if(month !=1)//如果不是2月,直接返回保存的当月天数
return daysOfMonth[month];
if(year%400==0 ||(year%100!=0 && year%4==0) )
return 29;
return daysOfMonth[month];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -