这个程序主要优3个.java文件组成,
MyCalendar.java (主要显示Calendar的方格和方格里面的数字,并根据日期确定每个小方格里的数字)
MyCalendarHeader.java (在Calendar的上方显示年和月,并能调整年,月,同时反映到Calendar.java中)
CalendarDemo.java (程序的运行类)
在编写这个程序的时候,主要遇到了如下几个问题:
1. 获得系统当前的时间Calendar.getInstance(); 里面最好加上TimeZone.getTimeZone("GMT+8:00"),要不然显示的日期会是错误的,比如系统时间为19号00:04分的时候,用Calendar.getInstance(); 调用返回的系统日期还是18号。
2. Calendar.MONTH返回的月份是 一月对应0,二月对应1;星期天对应1,星期一对应2,依此类推
//////////////MyCalendar.java////////////////////////
package MyCalendar;
import java.util.Calendar;
import java.util.TimeZone;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CustomItem;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;

public class MyCalendar extends CustomItem implements ItemCommandListener ...{
private final static Command CMD_SELECT = new Command("Select", Command.ITEM,1);
protected Display display;
private int rows = 6; //定义表格行数
private int cols = 7; //定义表格列数
private int dx = 20; //定义表格宽度
private int dy = 20; //定义表格高度
private int currentX = 0; //定义当前的行数
private int currentY = 0; //定义当前的列数
private Calendar cal; //记录当前的日期
private int curyear, curmonth, curday; //存储本机的年月日

private static int[] dayOfMonth = ...{31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31}; //保存非闰年的每个月的天数
private String[][] data = new String[rows][cols]; //存储日历表格中的数字
/**//*测试数据
private String[][] data = {{" 1"," 2"," 3"," 4"," 5"," 6"," 7"},
{" 8"," 9","10","11","12","13","14"},
{"15","16","17","18","19","20","21"},
{"22","23","24","25","26","27","28"},
{"29","30","31"," "," "," "," "},
{" "," "," "," "," "," "," "}
};
*/

public MyCalendar(String title, Display d) ...{
super(title);
display = d;
this.setDefaultCommand(CMD_SELECT);
this.setItemCommandListener(this);
cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8:00"));
curyear = cal.get(Calendar.YEAR);
curmonth = cal.get(Calendar.MONTH);
curday = cal.get(Calendar.DAY_OF_MONTH);
setData(curyear, curmonth, curday);
}

protected int getMinContentWidth() ...{
return (cols * dx) + 1;
}

protected int getMinContentHeight() ...{
return (rows * dy) + 1;
}

protected int getPrefContentWidth(int arg0) ...{
return (cols * dx) + 1;
}

protected int getPrefContentHeight(int arg0) ...{
return (rows * dy) + 1;
}

protected void paint(Graphics g, int w, int h) ...{
for (int i = 0; i <= rows; i++) ...{
g.drawLine(0, i*dy, cols*dx, i*dy);
}
for (int i = 0; i <= cols; i++) ...{
g.drawLine(i*dx, 0, i*dx, rows*dy);
}
int oldColor = g.getColor(); //保存当前颜色
g.setColor(0x00d0d0d0);
//填充灰色方格
g.fillRect((currentX * dx) + 1, (currentY * dy) + 1, dx - 1, dy - 1);
g.setColor(oldColor); //恢复原来颜色
//填写数字
for (int i = 0; i < rows; i++) ...{
for (int j = 0; j < cols; j++) ...{
if (data[i][j] != null) ...{
int oldClipX = g.getClipX();
int oldClipY = g.getClipY();
int oldClipWidth = g.getClipWidth();
int oldClipHeight = g.getClipHeight();
//设置裁减区大小,并填写数字
//注意:必须在setClip的地方写数字,要不然就写不上去的
g.setClip((j*dx) + 1, (i*dy) + 1, dx - 1, dy - 1);
//g.setColor(0x000000ff);
g.drawString(data[i][j], (j*dx) + 5, (i * dy) + 5, Graphics.TOP | Graphics.LEFT);
//恢复画布g的原来信息
g.setClip(oldClipX, oldClipY, oldClipWidth, oldClipHeight);
}
}
}
}
protected boolean traverse(int dir,
int viewportWidth,
int viewportHeight,
int[] visRect_inout) ...{
switch (dir) ...{
case Canvas.DOWN:
if (currentY < (rows - 1)) ...{
currentY++;
repaint(currentX * dx, (currentY - 1) * dy, dx, dy); //把上一次填灰的方块填白
repaint(currentX * dx, currentY * dy, dx, dy); //把当前方块填灰

} else ...{
return false;
}
break;
case Canvas.UP:
if (currentY > 0) ...{
currentY--;
repaint(currentX * dx, (currentY + 1) * dy, dx, dy); //把上一次填灰的方块填白
repaint(currentX * dx, currentY * dy, dx, dy); //把当前方块填灰
} else ...{
return false;
}
break;
case Canvas.LEFT:
if (currentX > 0) ...{
currentX--;
repaint((currentX + 1) * dx, currentY * dy, dx, dy); //把上一次填灰的方块填白
repaint(currentX * dx, currentY * dy, dx, dy); //把当前方块填灰
} else ...{
return false;
}
break;
case Canvas.RIGHT:
if (currentX < (cols - 1)) ...{
currentX++;
repaint((currentX - 1) * dx, currentY * dy, dx, dy); //把上一次填灰的方块填白
repaint(currentX * dx, currentY * dy, dx, dy); //把当前方块填灰
} else ...{
return false;
}
break;
}
visRect_inout[0] = currentX;
visRect_inout[1] = currentY;
visRect_inout[2] = dx;
visRect_inout[3] = dy;
//System.out.println(visRect_inout[0]);
//System.out.println(visRect_inout[1]);
//System.out.println(visRect_inout[2]);
//System.out.println(visRect_inout[3]);
return true;
}
//设置方格中需要显示的数字
public void setText(String text) ...{
data[currentX][currentY] = text;
repaint(currentY * dx, currentX * dy, dx, dy);
}

protected void setData(int year, int month, int day) ...{
//System.out.println(year + "--"+ month + "--"+ day);
//一月对应0,星期天对应1,星期一对应2,依此类推
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, 1); //用1是为了获得1号是星期几

int daysofmonth = getDaysOfMonth(year, month); //获得当前月的天数
int whichDay = cal.get(Calendar.DAY_OF_WEEK) - 1; //获得当前月的第一天是星期几(因为已经设置cal为1号)
int number = 1; //为下面的循环记录天数
data[0][0] = "日";
data[0][1] = "一";
data[0][2] = "二";
data[0][3] = "三";
data[0][4] = "四";
data[0][5] = "五";
data[0][6] = "六";

for (int i = 1; i < rows; i++) ...{
for (int j = 0; j < cols; j++) ...{
if (j < whichDay && i == 1) ...{
data[i][j] = "";
continue;
}
if (number <= daysofmonth) ...{
data[i][j] = String.valueOf(number);
number++;
continue;
}
data[i][j] = "";
}
}
//有可能日历五行显示不下,那么最后显示不下的那几天在第一行显示
for (int i = 0; number <= daysofmonth; i++,number++) ...{
data[1][i] = String.valueOf(number);
}
//设置当前日期在方格的位置以便填灰色
cal.set(Calendar.DAY_OF_MONTH,day); //由于刚才把当前天设为1号,现在为了显示当前天再设回来
int daysofweek = cal.get(Calendar.DAY_OF_WEEK); //记录当前天是一周的第几天
currentX = daysofweek - 1;
currentY = (day + whichDay) / 7 ;
if((day + whichDay) % 7 != 0) ...{ //如果不能整除
currentY++;
if (currentY > 5) ...{
currentY = 1;
}
}
}

private int getDaysOfMonth(int year, int month) ...{
if (month != 1) //如果不是2月
return dayOfMonth[month];
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
return 29;
return 28;
}

public void commandAction(Command c, Item i) ...{
}

public void setSelectedDate(int year, int month, int day) ...{
// if (day > getDaysOfMonth(year, month)) {
// day = getDaysOfMonth(year, month);
// }
//防止在调整月份的时候显示当前天会有问题(比如在8月31号就不能跳到9月31号)
day = (day>getDaysOfMonth(year, month))?getDaysOfMonth(year, month):day;
setData(year, month, day);
repaint();
}
}
////////////////MyCalendarHeader.java//////////////////////////
package MyCalendar;
import java.util.Calendar;
import java.util.TimeZone;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.CustomItem;
import javax.microedition.lcdui.Graphics;

public class MyCalendarHeader extends CustomItem ...{
//确定是选了年还是月
private final static int SELECT_YEAR = 0;
private final static int SELECT_MONTH = 1;
private final static int SELECT_NONE = 2;
private int location = SELECT_NONE; //开始默认为什么都没有选中
private Calendar cal;
private MyCalendar myCal;
private int year, month, day;

public MyCalendarHeader(String title, MyCalendar myCal) ...{
super(title);
this.myCal = myCal;
cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8:00"));
year = cal.get(Calendar.YEAR);
month = cal.get(Calendar.MONTH) + 1;
day = cal.get(Calendar.DAY_OF_MONTH);
}

protected int getMinContentWidth() ...{
return 130;
}

protected int getMinContentHeight() ...{
return 40;
}

protected int getPrefContentWidth(int arg0) ...{
return 130;
}

protected int getPrefContentHeight(int arg0) ...{
return 40;
}

protected void paint(Graphics g, int w, int h) ...{
int oldColor = g.getColor();

if (location == SELECT_YEAR) ...{
g.setColor(0x00d0d0d0);
g.fillRect(30, 2, 60, 18);
} else if (location == SELECT_MONTH) ...{
g.setColor(0x00d0d0d0);
g.fillRect(35, 22, 50, 38);
}
g.setColor(oldColor);
//保存裁减区
int oldClipX = g.getClipX();
int oldClipY = g.getClipY();
int oldClipWidth = g.getClipWidth();
int oldClipHeight = g.getClipHeight();
//设置裁减区的大小
g.setClip(30, 2, 100, 18);
g.drawString("<<" + String.valueOf(year) + "年>>", 31, 2, Graphics.LEFT | Graphics.TOP);
g.setClip(35, 22, 100, 38);
g.drawString("<<" + String.valueOf(month) + "月>>", 35, 22, Graphics.LEFT | Graphics.TOP);
//保存原来画布信息
g.setClip(oldClipX, oldClipY, oldClipWidth, oldClipHeight);
}
protected boolean traverse(int dir,
int viewportWidth,
int viewportHeight,
int[] visRect_inout) ...{
switch (dir) ...{
case Canvas.DOWN:
if (location == SELECT_YEAR) ...{
location = SELECT_MONTH;
} else if (location == SELECT_MONTH) ...{
location = SELECT_NONE;
return false;
} else if (location == SELECT_NONE) ...{
location = SELECT_YEAR;
}
repaint();
break;
case Canvas.UP:
if (location == SELECT_YEAR) ...{
location = SELECT_NONE;
return false;
} else if (location == SELECT_MONTH) ...{
location = SELECT_YEAR;
} else if (location == SELECT_NONE) ...{
location = SELECT_MONTH;
}
repaint();
break;
case Canvas.LEFT:
if (location == SELECT_YEAR) ...{
year--;
repaint();
myCal.setSelectedDate(year, month-1, day);
}
if (location == SELECT_MONTH) ...{
if (month > 1) ...{
month--;
} else ...{
month = 12;
}
repaint();
myCal.setSelectedDate(year, month-1, day);
}
break;
case Canvas.RIGHT:
if (location == SELECT_YEAR) ...{
year++;
repaint();
myCal.setSelectedDate(year, month-1, day);
}
if (location == SELECT_MONTH) ...{
month = month % 12 + 1;
repaint();
myCal.setSelectedDate(year, month-1, day);
}
break;
}
return true;
}
}
/////////////////CalendarDemo.java/////////////////////////////
package MyCalendar;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class CalendarDemo extends MIDlet implements CommandListener ...{
private final static Command CMD_EXIT = new Command("Exit", Command.EXIT,1);
private Display display;
private Form mainForm;

public CalendarDemo() ...{
mainForm = new Form("My Calendar");
}

protected void startApp() throws MIDletStateChangeException ...{
display = Display.getDisplay(this);
MyCalendar myCal = new MyCalendar("", display);
mainForm.append(new MyCalendarHeader("", myCal));
mainForm.append(myCal);
mainForm.addCommand(CMD_EXIT);
mainForm.setCommandListener(this);
display.setCurrent(mainForm);
}

protected void pauseApp() ...{
}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException ...{
}

public void commandAction(Command c, Displayable d) ...{
if (c == CMD_EXIT) ...{
try ...{
destroyApp(false);
} catch (MIDletStateChangeException e) ...{
e.printStackTrace();
}
notifyDestroyed();
}
}
}
程序运行效果如下:

本文介绍了一个使用Java编写的日历程序,由三个核心文件组成:MyCalendar.java负责展示日历和数字,MyCalendarHeader.java用于显示年月并调整日期,CalendarDemo.java作为程序入口。程序实现了日期选择和调整功能。
8655

被折叠的 条评论
为什么被折叠?



