日历表
- 作业要求
设计一个程序可以按月显示出指定年的日历,包括星期、月、日,如果有能力的同学可以添加上农历。
- 实验步骤
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class MyCalendar extends JApplet {
public static final String WEEK_SUN = "SUN";
public static final String WEEK_MON = "MON";
public static final String WEEK_TUE = "TUE";
public static final String WEEK_WED = "WED";
public static final String WEEK_THU = "THU";
public static final String WEEK_FRI = "FRI";
public static final String WEEK_SAT = "SAT";
public static final Color background = Color.white;
public static final Color foreground = Color.black;
public static final Color headerForeground = Color.blue;
public static final Color headerBackground = Color.white;
public static final Color selectedBackground = Color.blue;
public static final Color selectedForeground = Color.white;
private JPanel cPane;
private JLabel yearsLabel;
private JSpinner yearsSpinner;
private JLabel lunarLabel;
private static JTextField textField;
private JLabel monthsLabel;
private JComboBox monthsComboBox;
private JTable daysTable;
private AbstractTableModel daysModel;
private static Calendar calendar;
private static MyLunar lunar;
public MyCalendar()
{
cPane = (JPanel)getContentPane();
}
public void init()
{
cPane.setLayout(new BorderLayout());
calendar = Calendar.getInstance();
yearsLabel = new JLabel(" Year: ");
yearsSpinner = new JSpinner();
yearsSpinner.setEditor(new JSpinner.NumberEditor(yearsSpinner, "0000"));
yearsSpinner.setValue(new Integer(calendar.get(Calendar.YEAR)));
yearsSpinner.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent changeEvent)
{
//得到没触发此监听前的日期
int day = calendar.get(Calendar.DAY_OF_MONTH);
calendar.set(Calendar.DAY_OF_MONTH, 1);
//更改calendar中年份为用户所选年份,但月日并没有变
calendar.set(Calendar.YEAR, ((Integer)yearsSpinner.getValue()).intValue());
//得到用户所选年份的那个月的总天数
int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
//如果以前日期大于所选年份的同一月的的总天数,就……
calendar.set(Calendar.DAY_OF_MONTH, day>maxDay ? maxDay:day);
showLunar();
updateView();
}
});
JPanel yearMonthPanel = new JPanel();
cPane.add(yearMonthPanel, BorderLayout.NORTH);
yearMonthPanel.setLayout(new BorderLayout());
yearMonthPanel.add(new JPanel(), BorderLayout.CENTER);
JPanel yearPanel = new JPanel();
yearMonthPanel.add(yearPanel, BorderLayout.WEST);
yearPanel.setLayout(new BorderLayout());
yearPanel.add(yearsLabel,BorderLayout.WEST);
yearPanel.add(yearsSpinner, BorderLayout.CENTER);
monthsLabel = new JLabel("Month: ");
monthsComboBox = new JComboBox();
for(int i=1; i<=12; i++)
{
monthsComboBox.addItem(new Integer(i));
}
monthsComboBox.setSelectedIndex(calendar.get(Calendar.MONTH));
monthsComboBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
int day = calendar.get(Calendar.DAY_OF_MONTH);//同上
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.MONTH, monthsComboBox.getSelectedIndex());//修改calendar中的月份,其他不变
int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);//同上
calendar.set(Calendar.DAY_OF_MONTH, day>maxDay ? maxDay:day);//同上
showLunar();
updateView();
}
});
JPanel monthPanel = new JPanel();
yearMonthPanel.add(monthPanel, BorderLayout.EAST);
monthPanel.setLayout(new BorderLayout());
monthPanel.add(monthsLabel, BorderLayout.WEST);
monthPanel.add(monthsComboBox, BorderLayout.CENTER);
daysModel = new AbstractTableModel()
{
public int getRowCount()
{
return 7;
}
public int getColumnCount()
{
return 7;
}
public Object getValueAt(int row, int column)
{
if(row == 0)
{
return getHeader(column);
}
row--;
Calendar calendar = (Calendar)MyCalendar.this.calendar.clone();
//(假如现在calendar中月份为9月,以下也用9月)设置日期为9月1号
calendar.set(Calendar.DAY_OF_MONTH, 1);
int dayCount = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
//算出9月1号是星期几,因为calendar.get(Calendar.DAY_OF
//_WEEK)是返回一数字,星期日返回1,星期一返回2,等
//所以要对返回数减一
int moreDayCount = calendar.get(Calendar.DAY_OF_WEEK) - 1;
int index = row*7 + column;//表格中SUN所处位置为0行0列
//返回(row,column)应对应的月份号,例如:(2,1),则算出dayIndex为
//为7(2009年9月份的日期)
int dayIndex = index - moreDayCount + 1;
if(index<moreDayCount || dayIndex>dayCount)
{
return null;
}
else
{
return new Integer(dayIndex);
}
}
};
daysTable = new CalendarTable(daysModel, calendar);
daysTable.setCellSelectionEnabled(true);
daysTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
daysTable.setDefaultRenderer(daysTable.getColumnClass(0), new TableCellRenderer()
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
String text = (value==null)? "":value.toString();
JLabel cell = new JLabel(text);
cell.setOpaque(true);
if(row == 0)
{
cell.setForeground(headerForeground);
cell.setBackground(headerBackground);
}
else
{
if(isSelected)
{
cell.setForeground(selectedForeground);
cell.setBackground(selectedBackground);
}
else
{
cell.setForeground(foreground);
cell.setBackground(background);
}
}
return cell;
}
});
updateView();
cPane.add(daysTable, BorderLayout.CENTER);
JPanel lunarPanel = new JPanel();
lunarPanel.setLayout(new BorderLayout());
lunarLabel = new JLabel("Lunar: ");
textField = new JTextField();
textField.setHorizontalAlignment(JTextField.CENTER);
textField.setColumns(50);
lunarPanel.add(lunarLabel, BorderLayout.WEST);
lunarPanel.add(textField, BorderLayout.CENTER);
lunarPanel.add(new JLabel(""), BorderLayout.EAST);
cPane.add(lunarPanel, BorderLayout.SOUTH);
showLunar();
}
public static void showLunar()
{
lunar = new MyLunar(calendar);
textField.setText(lunar.cyclical()+"年"+lunar.getLunarDate()+ " " + lunar.animalsYear());
}
public static String getHeader(int index)
{
switch(index)
{
case 0:
return WEEK_SUN;
case 1:
return WEEK_MON;
case 2:
return WEEK_TUE;
case 3:
return WEEK_WED;
case 4:
return WEEK_THU;
case 5:
return WEEK_FRI;
case 6:
return WEEK_SAT;
default:
return null;
}
}
public void updateView()
{
daysModel.fireTableDataChanged();
daysTable.setRowSelectionInterval(calendar.get(Calendar.WEEK_OF_MONTH), calendar.get(Calendar.WEEK_OF_MONTH));
daysTable.setColumnSelectionInterval(calendar.get(Calendar.DAY_OF_WEEK)-1, calendar.get(Calendar.DAY_OF_WEEK)-1);
}
public static class CalendarTable extends JTable
{
private Calendar calendar;
public CalendarTable(TableModel model, Calendar calendar)
{
super(model);
this.calendar = calendar;
}
public void changeSelection(int row, int column, boolean toggle, boolean extend)
{
super.changeSelection(row, column, toggle, extend);
if(row == 0)
{
return;
}
Object obj = getValueAt(row, column);
if(obj != null)
{
calendar.set(Calendar.DAY_OF_MONTH,((Integer)obj).intValue());
showLunar();
}
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame("Calendar Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyCalendar myCalendar = new MyCalendar();
myCalendar.init();
frame.getContentPane().add(myCalendar);
frame.setLocation(200, 200);
frame.setSize(400, 200);
frame.setVisible(true);
}
}
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class MyLunar {
private int year;
private int month;
private int day;
private boolean leap;
static final String lunarMonth[] = {"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"};
static final String lunarDay[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};
static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
static final long[] lunarInfo = new long[]
{0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,
0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0};
//构造函数的作用是通过对下面四个辅助函数的使用,再结合参数cal,对year,month
//day,leap进行赋值,
public MyLunar(Calendar cal)
{
int offset;
int leapMonth = 0;
int days = 0;
Date baseDate = null;
try
{
baseDate = dateFormat.parse("1900年1月31日");
}
catch(ParseException e)
{
e.printStackTrace();
}
offset = (int)((cal.getTime().getTime() - baseDate.getTime())/86400000L) + 1;
//以下是对year进行赋值
int iYear;
for(iYear=1900; iYear<2050 && offset>0; iYear++)
{
days = daysOfYear(iYear);
offset -= days;
}
if(offset <= 0)
{
offset += days;
iYear--;
}
year = iYear;
//对year赋值结束
//以下是对month,day,leap进行赋值
leapMonth = monthOfLeap(iYear);
leap = false;
int iMonth;
for(iMonth=1; iMonth<=12 && offset>0; iMonth++)
{
if(leapMonth>0 && iMonth == (leapMonth+1) && !leap)
{
iMonth--;
leap = true;
days = daysOfLeapMonth(year);
}
else
{
days = daysOfMonth(year, iMonth);
}
offset -= days;
if(leap && iMonth == (leapMonth + 1)) leap = false;
}
if(offset <= 0)
{
offset += days;
iMonth--;
}
month = iMonth;
day = offset;
//对month,day,leap赋值结束
}
//下面四个函数是构造函数的辅助函数
private static final int daysOfYear(int y)
{
int i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1)
{
if ((lunarInfo[y - 1900] & i) != 0) sum += 1;
}
return (sum + daysOfLeapMonth(y));
}
private static final int daysOfLeapMonth(int y)
{
if (monthOfLeap(y) != 0)
{
if ((lunarInfo[y - 1900] & 0x10000) != 0)
return 30;
else
return 29;
} else
return 0;
}
private static final int monthOfLeap(int y)
{
return (int) (lunarInfo[y - 1900] & 0xf);
}
private static final int daysOfMonth(int y, int m)
{
if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
return 29;
else
return 30;
}
//根据year的值求生肖
public final String animalsYear()
{
final String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};
return Animals[(year - 4) % 12];
}
//根据year的值求干支,即:农历的年份(下面两个函数)
public final String cyclical()
{
int num = year - (1900 - 36); // 1900年为庚子年,36年前为甲子年,也就是说1864年为甲子年
return (cyclicalm(num));
}
private static final String cyclicalm(int num)
{
final String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
final String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
return (Gan[num % 10] + Zhi[num % 12]);
}
//根据month和day的值求农历日期(下面两个函数)
public final String getLunarDate()
{
return (leap ? "闰" : "") + lunarMonth[month - 1] + "月" + getLunarDay(day);
}
private static final String getLunarDay(int day)
{
String chineseTen[] = {"初", "十", "廿", "卅"};
int n = day % 10 == 0 ? 9 : day % 10 - 1;
if (day > 30)
return "";
if (day == 10)
return "初十";
else
return chineseTen[day / 10] + lunarDay[n];
}
}
- 实验结果