文档库 最新最全的文档下载
当前位置:文档库 › java日历记事本(无敌版带提醒功能调整时区更换图片铃声功能)

java日历记事本(无敌版带提醒功能调整时区更换图片铃声功能)

装订线

北京师范大学2015~2016学年春季学期期末Java程序设计作业试卷课程名称: Java程序设计任课教师姓名:孙一林

卷面总分: 100 分考试时长:分钟考试类别:闭卷□开卷

其他□院(系):信息科学与技术学院专业:计算机科学与技术年级: 2014 姓名:刁诗哲学号:

阅卷教师(签字):

评价准则:

(1)应用程序设计思想………………………………………………… ≤ 20% (2)程序结构表述……………………………………………………… ≤ 20% (3)调试、运行、结果………………………………………………… ≤ 20% (4)报告+程序文档………………………………………………………≤ 20% (5)应用程序展示(5分钟讲解与演示)……………………………≤ 10% (6)应用程序难易度……………………………………………………≤ 10%

设计要求:

选择一题,按自己理解设计程序,在报告(该试卷首页为报告第1页,文件名及格式为:*.doc或*.docx,* = 学号 + 姓名,报告为必要项)中给出设计思路、程序结构、调试、模拟运行、结果等说明内容,提交作业(设计、调试、运行、结果):报告+程序所有(源程序、类、打包等)文件的压缩文档(学号 + 姓名)。设计题目难易度依照题号顺序由小到大。

多功能日历记事本

一、整体介绍

1.外观显示

日历外观如下图所示,全局大体分为四个部分:左上,左下,右上,右下。

最上面是标题栏,显示该程序的名称,如我的程序显示的为“刁诗哲的日历”。标题栏下方为菜单栏,菜单栏目前有两个菜单,分别是“功能设置”和“关于”。

左上部分为日历界面,显示一个万年历,用户可以在输入框中输入所查年份和月份,按下回车后自动跳转到该月。左下部分是显示图片部分,用户可以自主设置自己喜欢的图片,设置这一功能主要是给用户提供个性化的用户体验,可以根据自己的喜

好设置喜爱的图片,比如放置一个名人座右铭可以勉励自己在学业上不断进步。右上为记事本区域,用户可以选中日期后输入自己想要保存的记事,同时,用户可以设置提醒时间(闹钟)。在右下方是一个钟表,不仅可以为用户提供实时查看时间的服务,同时也可以作为闹钟使用。

2.基本功能

1)万年历功能

左上方的日历相当于一个万年历,可以为用户提供一个日期的查看功能,可以显示日历的年月日,并且对今天的日历给出了特殊的显示(大字体和蓝色显示)。还能查看当前时间之前和之后的日历,可以通过按钮操作,也支持在输入框里面输入年和月。如上图

2)记事本的编辑、查看和删除功能

右上方提供备忘录(记事本)功能,用户可以记录下来之前发生的事情以作纪念,也可以记录下来未来想要做的事情以防遗忘

3)闹钟功能

用户点击设置闹钟时间后,便可以设置闹钟时间,到达预定时间后闹钟会播放音乐,当然,闹钟提醒音乐也可以自己设置。

4)使用帮助

3.高级功能

1)时区设置

我们为用户提供了多达75个时区的选择,点击更改时区即可将时间切换到当前用户所在的时区,可以满足用户去往不同国家的需求。是一款“国际化”日历。

2)自定义图片

用户点击更改图片背景,可以选择自己喜欢的图片,为用户提供了多样化选择。可以根据自己的喜好设置喜爱的图片,比如放置一个名人座右铭可以勉励自己在学业上不断进步。

3)自定义音乐

考虑到普通闹钟刺耳的缺点,我们给用户提供定制化铃声的功能,让用户可以自己设置闹钟铃声,提供了个性化的用户体验。

4)保留自定义设置

用户的自定义设置功能都会被记录,下次打开软件时还能保留先前的设置。是一款真正的人性化、个性化日历

二、设计思路

首先,按照功能将日历分成不同模块,分别是CalendarImage(显示图片),CalendarPad(实现主要功能,主要框架),mainclass(main方法),NotePad(显示

记事本),myClock(钟表的显示),Month(月份的设置和显示),Year(年份的设置和显示)。

图 1 根据功能设计日历模块

首先按照日历所要实现的功能,从外观显示和内部功能设计日历。

日历的外观共分为四个部分,分别是顶部的菜单栏,左上部分显示日历面板,右上部分显示记事本面板,左下部分显示图片,右下部分显示表盘,包括电子表显示和钟表表盘显示。

日历的内部功能:

实现记事本功能:包括获取日志,显示日志,删除日志

实现闹钟功能:包括钟表的显示,不同时区的设置,和到时提醒功能

日历日期的显示:包括月份的设置,年份的设置

根据以上功能的划分,按照面向对象编程的设计思想,将同一对象所应用的功能合并到一个对象上,可以将日历的实现划分为以下几个模块。

图 2 面向对象的日历设计

三、程序结构

1.总体结构

在设计多功能日历时,需要编写7个java源文件:mainclass.java, mainclass.java, NotePad.java , Year.java, Month.java,CalendarImage.java ,myClock.java。这些类的主要功能如下:

主类 mainclass(用于启动程序)

主要框架mainclass(是程序的核心)

记事本NotePad(记事本功能)

年Year(显示年)

月Month(显示月份)

日历图像CalendarImage(显示日历图像)

数字时钟myClock(用于显示数字时钟)

类之间的关系如下图所示

2.详细设计

mainclass.java

package diaoshizhe;

import java.util.Calendar;

//这是程序的主类;程序从这个类开始;

public class mainclass {

public mainclass() {

}

//main方法;

public static void main(String args[])

{

//创建一个日历的实例对象,返回当前时间;

Calendar calendar=Calendar.getInstance();

int y=calendar.get(Calendar.YEAR);

int m=calendar.get(Calendar.MONTH)+1;

int d=calendar.get(Calendar.DAY_OF_MONTH);

//新建一个CalendarPad类的对象,以参数形式传递获取的当前时间

new CalendarPad(y,m,d);

}

}

CalendarPad.java

成员变量:

int year,month,day; //存储当前的时间;

Calendar calendar; //日历对象;

int day_of_the_week; // 表示具体的星期几;

NotePad notepad=null; //记事本对象变量;

Month showMonth; //显示月份的区域的组件对象

Year showYear; //显示年份的区域的组件对象

Hashtable hashtable; //哈希表对象,用于写日志时文件的IO流;

File file; // file表示文件对象,用于写日志时文件的IO流;

JTextField showDay[]; // 单行文本编辑区域数组,用于显示日期;也是日历中每天的显示区域;

JLabel title[]; //标题栏,主要用于日历中星期几的标题栏;

CalendarImage calendarImage;//日历图像;

String picturename;//图像名称;用于更换图像时记录文件名

static String musicname;//音乐名称;用于用户更换闹钟铃声时记录文件名

String weekDay[]={"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};

JPanel leftUp,rightUp,leftWhole,rightWhole;//创建;

int ringhour,ringmin;

myClock clock;//时钟对象;

static String timeArea="Asia/Shanghai";

方法:

//构造方法

public CalendarPad(int year,int month,int day)

//增加鼠标监听器,按住鼠标的响应,为读取日志、写日志功能服务;

public void mousePressed(MouseEvent e) // 增加鼠标按钮的触发;

public void mouseClicked(MouseEvent e)

public void mouseReleased(MouseEvent e)

public void mouseEntered(MouseEvent e)

public void mouseExited(MouseEvent e)

//getPicture_address()方法,从文件中读到用户选择的图片文件的地址;

public String getPicture_address()

//getMusic_address()方法,从文件中读到用户选择的闹钟铃声文件的地址;

public String getMusic_address()

//getsettingtime()得到闹钟时间,从文件中读到先前设置的闹钟时间;

public void getsettingtime()

// 设置日历牌,但只是起到对不同月份的分类而已,通过调用sortDay()方法,把每个格要显示几号的任务交给调用方法;

public void setCalendar(int year,int month)

// 此方法供setCalendar()调用,用来设置每个格要显示几号;

public void sortDay(int day_of_the_week,int月天数)

//得到年;

public int getYear()

//设置年;

public void setYear(int y)

//得到月份;

public int getMonth()

//设置月份;

public void setMonth(int m)

//得到号数;

public int getDay()

//设置号数;

public void setDay(int d)

//获得hashtable;

public Hashtable getHashtable()

//获得文件;

public File getFile()

//事件监听器;

public void actionPerformed(ActionEvent e)

NotePad.java

成员变量:

JTextArea text;//定义一个编辑区域;

JButton save,delete;//定义两个按钮,保存,删除;

Hashtable table;

JLabel labelBar; //用于显示日期的标题;

int year,month,day;

File file;

CalendarPad calendar;

方法:

//构造函数,实现记事本显示、增删的主要功能;

public NotePad(CalendarPad calendar)

//监听按钮事件;

public void actionPerformed(ActionEvent e)

//设置年

public void setYear(int year)

//获取年;

public int getYear()

//设置月份;

public void setMonth(int month)

//获取月份;

public int getMonth()

//设置日;

public void setDay(int day)

//获取日;

public int getDay()

//设置标题栏的内容(日期);

public void setlabelBar(int year,int month,int day) //设置编辑区域显示的内容;

public void setTextArea(String s)

得到某个日期的日志内容;

public void getLogContent(int year,int month,int day) //保存日志的方法;

public void saveLog(int year,int month,int day)

//删除日志

public void deleteLog(int year,int month,int day)

myClock.java

package diaoshizhe;

import java.applet.Applet;

import java.applet.AudioClip;

import java.awt.*;

import java.io.File;

import https://www.wendangku.net/doc/5d17722904.html,.MalformedURLException;

import https://www.wendangku.net/doc/5d17722904.html,.URL;

import javax.swing.*;

import java.util.*;

import java.text.*;

public class myClock extends JApplet implements Runnable {

/**

*

*/

private static final long serialVersionUID = 1L;

Thread clock;

int ringhour;

int ringmin;

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone(CalendarPad.timeArea));

Date timenow;

Clock nowClock;

public myClock(){

start(); //开始进程

int w=getBounds().width;

int h=getBounds().height;

setBounds(0,0,w,h); //设置窗口尺寸

}

public void start(){

if (clock == null) {

clock = new Thread(this);

clock.start();

}

}

public void stop() {

clock = null;

}

public void run(){

while(true) {

repaint();

try{

Thread.sleep(1000);

}

catch(InterruptedException e){

}

}

}

@SuppressWarnings("deprecation")

public void paint(Graphics g) {

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone(CalendarPad.timeArea));

timenow = new Date();

calendar.setTime(timenow);

SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss a");

sdf.setTimeZone(TimeZone.getTimeZone(CalendarPad.timeArea));

String s_time_msg = sdf.format(timenow);

nowClock = new Clock(

calendar.get(Calendar.HOUR_OF_DAY),

calendar.get(Calendar.MINUTE),

calendar.get(Calendar.SECOND) );

g.clearRect(0,0,this.getWidth(),this.getHeight());

g.setFont(new Font("宋体", Font.BOLD, 22));

g.drawString(s_time_msg,70,400);

nowClock.show(g,230,210,150);

//闹钟功能:如果当前时间与设置的闹钟时间相同,则响铃;

if((ringhour==calendar.get(Calendar.HOUR_OF_DAY))&&(ringmin==calendar.ge

t(Calendar.MINUTE))&&(calendar.get(Calendar.SECOND)==0))

{

//播放指定音频;

try {

URL cb;

File f = new File(CalendarPad.musicname);//音频文件;

cb = f.toURL();

AudioClip aau;

aau = Applet.newAudioClip(cb); //创建AudioClip对象;

aau.play();//播放音频;

} catch (MalformedURLException e)

{

e.printStackTrace();

}

}

}

}

class Clock {

int hour,minute,second;

Clock(int hrs,int min,int sec) {

hour = hrs%12;

minute = min;

second = sec;

}

void show(Graphics g,int cx,int cy,int rad) {

int hrs_len = (int)(rad*0.5);

int sec_len = (int)(rad*0.9);

double theta;

g.drawOval(cx-rad,cy-rad,rad*2,rad*2);

theta=(double)(hour*60*60+minute*60+second)/43200.0*2.0*Math.PI ;

drawNiddle(g,Color.blue,cx,cy,hrs_len,theta);

theta=(double)(minute*60+second)/3600.0*2.0*Math.PI ;

drawNiddle(g,Color.red,cx,cy,sec_len,theta);

theta=(double)(second)/60.0*2.0*Math.PI ;

drawNiddle(g,Color.green ,cx,cy,sec_len,theta);

}

private void drawNiddle(

Graphics g,Color c,int x,int y,int len,double theta){

int ex = (int)(x+len*Math.sin(theta));

int ey = (int)(y-len*Math.cos(theta));

g.setColor (c);

g.drawLine(x,y,ex,ey);

}

}

Year.java

package diaoshizhe;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

//继承Box,显示日历上的年份

public class Year extends Box implements ActionListener

{

/**

*

*/

private static final long serialVersionUID = 1L;

int year; //定义年;

JTextField showYear=null;//显示年的区域;

JButton nextYear,lastYear;//定义按钮;

CalendarPad calendar;//日历;

//构造方法;

public Year(CalendarPad calendar)

{

super(BoxLayout.X_AXIS);//用super继承父类的构造方法,box中的组件从左到右布置器件;

showYear=new JTextField(4); //区域大小设置;

showYear.setForeground(Color.blue); //显示字体颜色;

showYear.setFont(new Font("TimesRomn",Font.BOLD,14)); //设置字体,大小;

//把calendar的时间传进来;

this.calendar=calendar;

year=calendar.getYear();

//新建按钮;

nextYear=new JButton("下年");

lastYear=new JButton("上年");

//添加按钮;

add(lastYear);

add(showYear);

add(nextYear);

//添加事件监听器;

showYear.addActionListener(this);

lastYear.addActionListener(this);

nextYear.addActionListener(this);

}

//设置年;

public void setYear(int year)

{

this.year=year;

showYear.setText(""+year);

}

//获取年;

public int getYear()

{

return year;

}

//事件监听方法;

public void actionPerformed(ActionEvent e)

{

//如果点击的是lastyear按钮;

if(e.getSource()==lastYear)

{

//年减去一年,重新设置日历;

year=year-1;

showYear.setText(""+year);

calendar.setYear(year);

calendar.setCalendar(year,calendar.getMonth()); }

//如果点击的是nextyear按钮;

else if(e.getSource()==nextYear)

{

//年增加一年,重新设置日历;

year=year+1;

showYear.setText(""+year);

calendar.setYear(year);

calendar.setCalendar(year,calendar.getMonth());

}

//如果是在显示年的区域内写入东西;

else if(e.getSource()==showYear)

{

try

{

//获取写在该区域的内容,转化为整型,赋给year,重新设置日历;

year=Integer.parseInt(showYear.getText());

showYear.setText(""+year);

calendar.setYear(year);

calendar.setCalendar(year,calendar.getMonth()); }

catch(NumberFormatException ee)

{

showYear.setText(""+year);

calendar.setYear(year);

calendar.setCalendar(year,calendar.getMonth()); }

}

}

}

Month.java

package diaoshizhe;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

//继承Box,用于显示日历上的月份,并可选择上月,下月;

public class Month extends Box implements ActionListener

{

/**

*

*/

private static final long serialVersionUID = 1L;

int month;

JTextField showMonth=null;

JButton nextMonth,lastMonth;

CalendarPad calendar;

public Month(CalendarPad calendar)

{

super(BoxLayout.X_AXIS);//用super继承父类的构造方法,box中的组件从左到右布置器件;

//把calendar的时间传进来;

this.calendar=calendar;

showMonth=new JTextField(2);//区域大小设置

month=calendar.getMonth();

showMonth.setForeground(Color.blue); //显示字体颜色

showMonth.setFont(new Font("TimesRomn",Font.BOLD,16)); //设置字体,大小;

//新建按钮;

nextMonth=new JButton("下月");

lastMonth=new JButton("上月");

//添加按钮;

add(lastMonth);

add(showMonth);

add(nextMonth);

//添加事件监听器;

showMonth.addActionListener(this);

lastMonth.addActionListener(this);

nextMonth.addActionListener(this);

showMonth.setText(""+month);

}

//设置月份;

public void setMonth(int month)

{

if(month<=12&&month>=1)

{

this.month=month;

}

else

{

this.month=1;

}

showMonth.setText(""+month);

}

//获取月份;

public int getMonth()

{

return month;

}

//事件监听方法;

public void actionPerformed(ActionEvent e)

{

//按下lastMonth按钮

if(e.getSource()==lastMonth)

{

//如果month>2,则month直接减1,重设置日历;

if(month>=2)

{

month=month-1;

calendar.setMonth(month);

calendar.setCalendar(calendar.getYear(),month);

}

//如果month==1,则year-1,而month为12,重设日历;

else if(month==1)

{

month=12;

int year=calendar.getYear()-1;

calendar.setMonth(month);

calendar.setYear(year);

calendar.setCalendar(year,month);

}

showMonth.setText(""+month); //显示内容的设置;

}

// 如果nextMonth按钮被按下;

else if(e.getSource()==nextMonth)

{

//如果month小于12,则month直接加1,再重设日历;

if(month<12)

{

month=month+1;

calendar.setMonth(month);

calendar.setCalendar(calendar.getYear(),month);

}

//如果month=12,那么year+1,并且month变为1,再重设日历;

else if(month==12)

{

month=1;

calendar.setYear(calendar.getYear()+1);

calendar.setMonth(month);

calendar.setCalendar(calendar.getYear(),month);

}

showMonth.setText(""+month);//设置显示内容;

}

else if(e.getSource()==showMonth)

{

month=Integer.parseInt(showMonth.getText());

if((month>=1)&&(month<=12)){

try

{

calendar.setMonth(month);

calendar.setCalendar(calendar.getYear(),month);

}

catch(NumberFormatException ee)

{

//showMonth.setText(""+month);

calendar.setMonth(month);

calendar.setCalendar(calendar.getYear(),month);

}

}

showMonth.setText(""+month);

}

}

}

CalendarImage.java package diaoshizhe;

import javax.swing.*;

import java.io.*;

import java.awt.*;

//继承了JPanel类,用于显示图片;

public class CalendarImage extends JPanel {

/**

*

*/

private static final long serialVersionUID = 1L;

File imageFile;//定义文件;

Image image;//定义图片;

Toolkit tool;//定义工具;

//构造方法

public CalendarImage() {

tool=getToolkit();//获取工具;

}

//设置图像文件;

public void setImageFile(File f)

{

imageFile =f;

try{

image=tool.getImage(imageFile.toURI().toURL());//得到图像文件;

}

catch (Exception eeee)

{

}

repaint();//重绘;

}

//重载paintComponent方法

public void paintComponent(Graphics g)

{

super.paintComponent(g);

int w=getBounds().width;

int h=getBounds().height;

g.drawImage(image,0,0,w,h,this);

}

}

四、调试

在调试过程中遇到了很多问题,可以说是一边写代码一遍调试的(个人认为这也是正确方法,如果写完所有代码再调试就太晚了),在调试的过程中遇到了很多问题,在这里举最关键的,印象最深的问题列举。

遇到的问题1:

日历面板如何设计,怎样才能较完整的实现日历的功能,在这个方面的设计我头脑有点晕,分不清几个模块如何拼接在一起。如何显示日历面板,通过百度我搜索了一下前人的经验,又看了一些优秀案例,同时参照自己电脑上的日历,有了解决方法。

解决:

设置一个大的JPanel叫做leftUp(因为左上角是日历,所以名字叫leftUp),然后设置几个小的组建,分别是

JPanel leftUp_center=new JPanel();// leftUp_center为窗口的leftUp的中间部分,用于显示日历;

JPanel leftUp_north=new JPanel();//leftUp_north为窗口的leftUp的上部分,用于显示年月及相关按钮;

JPanel leftUp_center_east=new JPanel();//leftUp_center_east是窗口的leftUp_center的东边部分,用来显示日历每天的星期和号数;

使用以上方法就将一个大的日历划分成几个小的模块,然后一一实现就简单了

相关文档