基于Java的万年历(课设)

基于Java的万年历

资源链接:基于Java的万年历(课设)

文章目录

  • 基于Java的万年历
  • 1 绪论
  • 2 需求分析
  • 3 概要设计
    • 3.1 类间组合框架
    • 3.2 布局结构示意
    • 3.3 对各个类的概述
  • 4运行环境
  • 5 开发工具和编辑语言
  • 6 详细设计
    • 6.1 NiceCaelendar类
    • 6.2 NiceFrame类
    • 6.3 NiceClock类
    • 6.4 NiceMenubar类
    • 6.5 NicePanel类
    • 6.6 NiceBase类
    • 6.7 NiceAlarm类
    • 6.8 NiceTimer类
    • 6.9 NiceLabels类
  • 7 调试分析
    • 7.1 `0:-1:59问题`
    • 7.2 菜单条的颜色问题
    • 7.3 时差问题
    • 7.4 功能补充
  • 8 测试结果
    • 8.1 跳转功能
    • 8.2 换肤功能
    • 8.3 定时功能
    • 8.4 显示关于
  • 9 总结与展望

摘 要

Java编程语言自诞生十几年来,已经成功地运用在网络计算及移动等各个领域。对于开发者来说,它具有简单、面向对象、健壮、安全、结构中立、可移植和高效能等众多优点。此次我们用JAVA来设计一个万年历程序,该程序以网页形式运行,并且支持图形化界面,能以日历的形式显示日期与星期,用户能自己输入日期,支持查找日期,并且能够更新日期,是一个简单易用的小应用。

关键词:JAVA,图形化界面,万年历

1 绪论

Java的前身是Oak,它一开始只是被应用于消费性电子产品中。后来它的开发者们发现它还可以被用于更大范围的Internet上。l995年,Java语言的名字从0ak编程了Java。1997年J2SE1.1发布。1998年J2SE1.2发布,标志Java2的诞生。十多年来,Java编程语言及平台成功地运用在网络计算及移动等各个领域。Java的体系结构由Java语言、Java class、Java API、Java虚拟机组成。它具有简单、面向对象、健壮、安全、结构中立、可移植和高效能等众多优点。Java支持多线程编程,Java运行时系统在多线程同步方面具有成熟的解决方案。Java的平台标准有Java ME,Java SE和Java EE。Java发展到今天,它的卓越成就及在业界的地位毋庸置疑。目前在众多的支持Java的开发工具中主要的7JavaDevelopment Kit,NetBeans,Jcreator,JBuilder,JDeveloper和Eclipse等。其中Java Development Kit简称JDK是大多开发工具的基础。以上的每种开发工具都有优缺点,对于开发者来说,重要的是要根据自己的开发规模、开发内容和软硬件环境等因素来选择一种合适的开发工具。

2 需求分析

对于日期,1、3、5、7、8、10、12月有31天;4、6、9、11月有30天;闰年的2月有29天,平年有28天。每4年一个闰年,每100年一个闰年,每400年一个闰年。根据以上条件,给定任意的年份和月份,便可计算出当月的天数。

对于时间,将表盘分为12等份,每一份对应一小时;将表盘分为60等份,每一份对应一分钟;将表盘分为3600等份,每一份对应一秒钟。

每秒钟分针转过的角度:minute_angle=(minute+second/60)*360/60;

每秒钟时针转过的角度:hour_angle=(hour-12+minute/60)*360/12;

根据以上条件,便可以计算出任意时刻时分秒针在表盘上的具体位置,利用Graphics2D类在面板上绘制即可。

将标签和日期进行关联这样就可以将日期的具体信息显示出来,比如节假日、每日运势、黄道吉日等。

通过调用系统时间,制作一个计时装置,结合窗口和标签实现闹钟的功能。

通过设置时钟、日历、标签等的背景和背景图片可以实现更改界面风格,从而实现换肤功能。

再结合菜单、面板、标签、按钮,做出一个简单实用的可视化图形用户界面。

万年历是一个非常实用的小工具。然而在当代,万年历的功能已经不仅仅局限于看时间、查日期的功能了。为此,本系统加入了更加人性化的换肤功能,以及设置闹钟的功能。让小小的万年历全面接管时间!

3 概要设计

3.1 类间组合框架

为了实现代码复用、降低源程序各个模块内的耦合性以及方便修改源代码,将各个类按照层次自顶向下分层设计。利用对象组合的设计方法,让上层类组合下层类的对象,尽量将功能下沉。

各个类之间的组合关系如图所示:

在这里插入图片描述

图3-1 类之间的组合关系

3.2 布局结构示意

万年历的主框架在一个NiceFrame里,通过继承JFrame而来。包含NiceMenubar、NicePanel、Panel_Left三大模块。

NiceMenuba包含Start、Function、Help三个菜单;当用户点击菜单项的时候,对应的部分会做出反馈并显示在面板上。

Panel_Left上边放NIceClock,下边放NiceLabels;NiceLabels包含三个标签,通过监听日历的点击事件显示内容。

NicePanel使用BorderLayout布局,分为Panel_North、Panel_Center、Panel_South三个部分;Panel_Center负责通过调用NiceBase获得计算出的日历格式,并显示在面板上。

各模块的窗口布局如图所示:

在这里插入图片描述

图3-2 布局示意图

3.3 对各个类的概述

在这里插入图片描述

图3-3 程序UML图

NiceCalendar类,包含程序的入口,对窗口的基本设置,如窗口大小、图标、名称等。

public class NiceCalendar{
NiceFrame NF; 
} 

NiceFrame类,继承JFrame类,是程序的主框架负责窗口的整体布局。

public class NiceFrame extends JFrame{
NiceClock NC; 
  NiceMenubar NM;  
  JPanel Panel_Left;
}

NiceClock类,继承JPanel,实际上是一个面板,通过重载paintComponent方法,利用Graphics2D将时钟绘制在面板上。

class NiceClock extends JPanel{
ImageIcon I; 
NiceClock(ImageIcon I){}
public void paintComponent(GraphicsG){}  
}

NiceMenuBar类,继承了JMenuBar;组合了NiceClock,实现对时钟的换肤功能;实现ActionListener接口,对菜单项进行事件监听。定义的changeSkin方法对全局更改背景颜色。

public class NiceMenubar extends JMenuBar implements ActionListener{
  NicePanel NP;
  NiceClock NC;
NiceMenubar(NiceClock NC){}
public void actionPerformed(ActionEvent e){}
public void changeSkin(Color C){}
}

NiceSkip类,继承JFrame,引用NicePanel,主要功能是在Skip按钮按下后,调用NicePanel的refresh方法刷新日历。

public class NiceSkip extends JFrame implements ActionListener{
   NicePanel NP;
void Skip(NicePanel NP){}
public void actionPerformed(ActionEvent e){}
}

NicePanel类,组合了NiceBase和NiceLabels,负责日历的绘制与刷新,在标签上显示日期、节日、占卜。

pJAublic class NicePanel extends JPanel implements ActionListener {
  NiceBase NB;
  NiceLabels NL;
void refresh(){}
public void actionPerformed(ActionEvent e) {}
}

NiceBase类,提供日历的计算方法,接收指定的年份和月份,并返回一个当月日历的数组。

public class NiceBase{
  //String day[];
  pricate int year;
  private int month;
public void setYear(int year){} 
public int getYear(){}
public void setMonth(int month){}
public int getMonth(){} 
public String[] getCalendar(){}
}

NiceLabels类,包含三个标签,用来显示节日、占卜、闹钟。

public class NiceLabels extends JPanel{ 
Color C;
Random R;
String getTips(){}
void getRemind(int num){}
}

NiceAlarm类,继承JFramen类,是一个弹出窗口,接收TextField输入的时间,并调用NiceTimer类计时。

public class NiceAlarm extends JFrame implements ActionListener{
NiceLabels NL;
}

NiceTimer类,接收时间,根据系统当前时间进行倒计时。

Public class NiceTimer{
  NiceLabels NL; 
  int goalHour;
  int goalMinute;
public void run() {}
}

根据需求分析,能够得出需要哪些功能、哪些类。定义这些类,构建类之间的组合关系,为之后的详细设计奠定基础。系统中各个类都是一个整体,使用组合的方法,当需要使用某个标签、按钮的时候仅仅去调用即可,降低代码的耦合性。

在使用Java的Calendar类获取当前日期的时候,需要进行换算。因为国外的星期的第一天是Sunday,而中国一周的第一天是Monday,这就是文化差异。为了规避差异,需要将Calendar.get(Calendar.DAY_OF_WEEK)-1;还有时差的问题:使用System.currentTimeMillis(); 获取的系统时间解析后得到的时间与我国的时间不一致,这是因为我国所处的时区是东八区,因此需要加上八个时区才可以,这在换算的时候应该考虑到。

4运行环境

Java Development Kit 8

Windows 10

Intel® Core™ i5-10300H

2.50GHz CPU主频

8GB RAM

256GB SSD

5 开发工具和编辑语言

IntelliJ IDEA 2022.1.3

Java

6 详细设计

6.1 NiceCaelendar类

在这里插入图片描述

图6-1 NiceClendar UML图

设置窗口属性,提供程序的入口方法。

public class NiceCalendar{                
  public static void main(String[] args){ //main方法 //程序入口
    NiceFrame NF = new NiceFrame();    //Window//组合
    NF.setBounds(200,200,1200,600);  //设置窗口大小 //1200X600
    Image image =                  // 将图片转换为Image对象        Toolkit.getDefaultToolkit().createImage("logo.jpg"); 
    NF.setIconImage(image);       //设置窗口图标
    NF.setTitle("Nice Calendar");      //title //窗口标题
    NF.setVisible(true); //let the window visible //窗口可见
}; // main结束
} // NiceCalendar类的结束

6.2 NiceFrame类

在这里插入图片描述

图6-2 NiceFrame UML图

JFrame类型的窗口,将窗口分为菜单、左上、左下、右四个部分。菜单放NiceMenuBar;左上放NiceClock;左下放NiceLabels;右放NicePanel。

NiceClock NC = new NiceClock(new ImageIcon("WHITE.jpg")); // 背景
NiceMenubar NM = new NiceMenubar(NC);     // 组合NiceMenu
JPanel Panel_Left = new JPanel(new GridLayout(2, 1));   // 设置布局
/*set layout //设置布局 将面板分成上下两等*/
public NiceFrame(){  // 构造器
setVisible(true);                // 可见
setDefaultCloseOperation(DISPOSE_ON_CLOSE);      // 处理
Panel_Left.add(NC);              // 添加NiceClock
Panel_Left.add(NM.NP.NL);          // 添加NiceLabels
setLayout(new GridLayout(1, 2));           // 设置布局
  setJMenuBar(NM);                  // 添加菜单栏
add(Panel_Left);             // 添加Panel_Left
add(NM.NP);            // 添加NicePanel
 NM.NP.refresh();                  // 显示默认日历
} // 构造函数结束

在这里插入图片描述

图6-3 NiceClock UML图

6.3 NiceClock类

NiceClock类,继承JPanel类,通过重写父类的printComponent方法将表盘绘制在面板上。绘制过程包括:打开抗锯齿、放入背景图片、计算表盘半径、绘制数字、绘制刻度、绘制时针、绘制分针。

public void paintComponent(Graphics G){ //draw components
    Graphics2D G2D = (Graphics2D)G;
    G2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);     //抗锯齿 使指针显示逼真
G2D.setColor(Color.RED); //前景颜色
    G2D.drawImage(I.getImage(),0,0,getWidth(),getHeight(),
I.getImageObserver()); //set background
int x_Width = this.getWidth() / 2; //get the width of panel
    int y_Width = this.getHeight() / 2; //get the height of panel
    int radius = (int) (Math.min(this.getWidth(), this.getHeight()) * 0.8 * 0.5); //calculate the radius of clock
    for(int i = 0; i < 12; i++){ 
      double angle = Math.PI / 180 * i * (360 / 12); 
      int x = (x_Width - 4) + (int)((radius - 12) * Math.cos(angle)); 
      int y = (y_Width + 4) + (int)((radius - 12) * Math.sin(angle)); 
      int j = i + 3;
      if (j > 12) 
        j = j - 12; 
      G2D.drawString(Integer.toString(j), x, y); //add numbers to clock       
    }
       AffineTransform old = G2D.getTransform();    
/*transform 2D coordinates to another*/
    for (int i = 0; i < 60; i++){ 
       int w = i % 5 == 0 ? 6 : 3;  //判断刻度的大小
       G2D.fillRect(x_Width - 2, 28, w, 3);      //绘制刻度
       G2D.rotate(Math.toRadians(6), x_Width, y_Width);
       } // add marks to clock
    G2D.setTransform(old);
    Calendar C = Calendar.getInstance();
    int hour = C.get(Calendar.HOUR_OF_DAY);
    int minute = C.get(Calendar.MINUTE);
    int second = C.get(Calendar.SECOND);

double hour_angle = (hour - 12 + minute / 60d) * 360d / 12d;

G2D.rotate(Math.toRadians(hour_angle), x_Width, y_Width);

int x_hour_array[] = { x_Width, x_Width + 9, x_Width, x_Width - 9 };

 int y_hour_array[] = { 65, y_Width, y_Width + 10, y_Width };

 G2D.drawPolygon(x_hour_array, y_hour_array, x_hour_array.length);//绘制时针

G2D.setTransform(old);
   

double minute_angle = (minute + second / 60d) * 360d / 60d;

 G2D.rotate(Math.toRadians(minute_angle), x_Width, y_Width);

 int x_minute_array[] = { x_Width, x_Width + 6, x_Width, x_Width - 6 };//分针长度

int y_minute_array[] = { 45, y_Width, y_Width + 12, y_Width };     

 G2D.drawPolygon(x_minute_array, y_minute_array, x_minute_array.length);

//绘制分针

 G2D.setTransform(old);

 }

 NiceClock(ImageIcon I){

    this.I = I;      //接收背景图片

  }

6.4 NiceMenubar类

在这里插入图片描述

图6-4 NiceMenubar UML图

NiceMenubar类,负责控制万年历所有的功能。起到承上启下的关键作用。changeSkin方法通过设置各个按钮、标签的背景颜色完成换肤功能。其中,日历中的42个按钮用for循环遍历设置。

public void changeSkin(Color C){    // 设置各种背景
    NP.NL.setBackground(C);
    NP.Button_Current.setBackground(C);
    NP.Button_Current.setBackground(C);
    NP.Button_lastYear.setBackground(C);
    NP.Button_nextYear.setBackground(C);
    NP.Button_lastMonth.setBackground(C);
    NP.Button_nextMonth.setBackground(C);
    NP.Panel_South.setBackground(C);
    NP.Panel_North.setBackground(C);
    NP.Panel_Center.setBackground(C); 
    NP.Label_Year.setBackground(C);
    NP.Label_Month.setBackground(C);
    NP.Label_Calendar.setBackground(C); 
    for(int i = 0; i < 42; i ++){
      NP.Button_Day[i].setBackground(C);
    }

  } // 换肤结束

} // NiceMenubar类结束

6.5 NicePanel类

在这里插入图片描述

图6-5 NicePanel UML图

NicePanel类,用for循环将按钮加入到面板里并设置按钮颜色和字体。refresh方法用来重新获取日历并显示。

NicePanel(){
    setLayout(new BorderLayout());       // 边界布局
    Label_Calendar.setFont(new Font("Arove", 1, 30)); 
    Label_Calendar.setForeground(Color.RED);                          
    Panel_Center.setLayout(new GridLayout(7, 7));   // 布局:7X7网格
    for(int i = 0; i < 7; i++){        // 将week[]添加到面板
      Label_Week[i] = new JLabel(Week[i], JLabel.CENTER);               
      Label_Week[i].setFont(new Font("Arvo", 1, 20));
      Label_Week[i].setForeground(Color.GREEN);
      Label_Week[i].setBackground(NL.C);
      Panel_Center.add(Label_Week[i]);
    }                       
    for(int i = 0; i < 42; i++){       //add day[]添加到面板
      Button_Day[i] = new JButton("None");
      Button_Day[i].setBorder(BorderFactory.createLineBorder(Color.WHITE));
      Panel_Center.add(Button_Day[i]);                    
    } 
}

void refresh(){
    String day[] = NB.getCalendar();
    String month;
    for(int i = 0; i<42; i++){                        
      Button_Day[i].setForeground(Color.CYAN);
      Button_Day[i].setFont(new Font("Arove", 1, 22));
      Button_Day[i].setText(day[i]); 
    }
    switch(NB.getMonth()){
      case 1:month = " 一月 ";break;
      case 2:month = " 二月 ";break;
      case 3:month = " 三月 ";break;
      case 4:month = " 四月 ";break;
      case 5:month = " 五月 ";break;
      case 6:month = " 六月 ";break;
      case 7:month = " 七月 ";break;
      case 8:month = " 八月 ";break;
      case 9:month = " 九月";break;
      case 10:month = " 十月 ";break;
      case 11:month = " 十一月 ";break;
      case 12:month = " 十二月 ";break;
      default:month = " NULL ";
    }
    Label_Year.setText(" "+ NB.getYear() +" ");
    Label_Month.setText(month);
  }

6.6 NiceBase类

在这里插入图片描述

图6-6 NiceBase UML图

NiceBase类,包括设置年月的方法和获取年月的方法以及获取日历按钮数字的方法。

public void setYear(int year){      //设置年份
    if(year < 2119 && year > 1919)           
    this.year = year;                       
 }                          
 public int getYear(){           //返回年份
    return year;                        
 }          
 
 public void setMonth(int month){      //设置月份
    if(month < 0)       
    this.month = month + 12;
    else if(month > 12)   
    this.month = month -12; 
    else
    this.month = month;                  
 }                               
 public int getMonth(){          //返回月份
    return month;
  }                               

  public String[] getCalendar(){       //绘制日历
    String a[] = new String[42];
    Calendar C = Calendar.getInstance();
    C.set(year, month - 1, 1);        //月份以0为基数
    int D = C.get(Calendar.DAY_OF_WEEK)-1;
    
    int day = 0;
    if(month == 1||month == 3||month == 5||month == 7||month == 8||month == 10||month == 12)
      day = 31; // 1 3 5 7 8 10 12他们每月有31天
      
    else if(month == 4||month == 6||month == 9||month == 11)
      day = 30; // 4 6 9 11他们一个月有30天
      
    else if(month == 2){
      if(((year % 4 == 0)&&(year % 100!= 0))||(year % 400 == 0))
        day = 29; // 有时29,否则28
      else
        day = 28; 
    } 
    for(int i = D, n = 1; i < D + day; i++){
      a[i] = String.valueOf(n);
      n++;
    }
    return a;
  }
}

6.7 NiceAlarm类

在这里插入图片描述

图6-7 NiceAlarm UML图

NiceAlarm类,当set按钮被按下时,转到NiceTImer类去执行。

public void actionPerformed(ActionEvent e){
    
    if(e.getSource() == Textfield_H){
      NL.Label_Alarm.setText("Alarm: "+ 
      Textfield_H.getText() +":"+ Textfield_M.getText());
      
    }
    if(e.getSource() == Textfield_M){
      NL.Label_Alarm.setText("Alarm: "+ 
      Textfield_H.getText() +":"+ Textfield_M.getText());
    }
    if(e.getSource() == Button_Set){
      
      this.dispose();
      new NiceTimer(Integer.valueOf(Textfield_H.getText()),
      Integer.valueOf(Textfield_M.getText()), NL).run();
      
    }

  }

6.8 NiceTimer类

在这里插入图片描述

图6-8 NiceTimer UML图

NiceTimer类,run方法每秒获取一次当前时间,并与目标时间计算后得出差值显示到终端。

public void run() {
    int currentSecond;
    int currentMinute;
    int currentHour;
    
    do{
      long currentTime = System.currentTimeMillis();  // 获取当前时间

      currentTime = currentTime / 1000;
      currentSecond = (int) (currentTime % 60);     // 获得第二
      currentTime = currentTime / 60;
      currentMinute = (int) (currentTime % 60);     // 获取分钟
      currentTime = currentTime / 60;   
      currentHour = (int) (currentTime % 24);      // 获取小时数
      
      if (goalMinute-currentMinute > 0)
      System.out.println("闹钟: "+ (goalHour-currentHour) +" : "+
      (goalMinute-currentMinute-1) +" : "+ (59-currentSecond));
      
      try {
        Thread.sleep(1000);        // 系统暂停一秒钟
      }
      catch (InterruptedException e){
        e.toString();
      } 
    }while (goalHour*100+goalMinute > currentHour*100+currentMinute);
    
    NL.Label_Alarm.setText("闹钟:时间到!"); // 时间到

  }

}

6.9 NiceLabels类

在这里插入图片描述

图6-9 NiceLabels UML图

NiceLabels类,主要功能是设置标签内容,getTips()方法和getRemind()方法可以返回对应日期的占卜和节日。

String getTips(){
   int i = R.nextInt(10);
   String S[] = new String[10];
   S[0] = "小贴士:既不好也不坏";
   S[1] = "小贴士:不喝酒/不旅行/不参加葬礼";
   S[2] = "小贴士:参观/贸易/理发/旅行";
   S[3] = "小贴士:禁止砍伐/结婚/洗澡";
   S[4] = "小贴士:不要祈祷/建造/种植";
   S[5] = "小贴士:无所事事/倒霉的一天";
   S[6] = "小贴士:祈祷/结婚/洗澡/旅行";
   S[7] = "小贴士:不结婚/不游泳/装饰";
   S[8] = "小贴士:禁止建造/禁止交易/砍伐树木";
   S[9] = "小贴士:一切顺利";

   return S[i];
}
void getRemind(int num){
   switch(num){
     case 11: Label_Remind.setText("提醒:1月1日元旦");break;
     case 214: Label_Remind.setText("提醒:2月14日情人节");break;
     case 38: Label_Remind.setText("提醒:3月8日妇女节");break;
     case 41: Label_Remind.setText("提醒:4月1日愚人节");break;
     case 422: Label_Remind.setText("提醒:4月22日地球日");break;
     case 51: Label_Remind.setText("提醒:五一劳动节");break;
          case 54: Label_Remind.setText("提醒:五四青年节");break;
          case 57: Label_Remind.setText("提醒:五七回华诞");break;
     case 61: Label_Remind.setText("提醒:6月1日儿童节");break;
     case 71: Label_Remind.setText("提醒:七一建党纪念日");break;
          case 81: Label_Remind.setText("提醒:8月1日建军节");break;
          case 96: Label_Remind.setText("提醒:9月6日我的生日");break;
     case 910: Label_Remind.setText("提醒:9月10日教师节");break;
     case 101: Label_Remind.setText("提醒:10月1日国庆节");break;
     case 1128: Label_Remind.setText("提醒:11月28日感恩节");break;
     case 1224: Label_Remind.setText("提醒:12月24日平安夜");break;
     case 1225: Label_Remind.setText("提醒:12月25日圣诞节");break;
     default: Label_Remind.setText("提醒:NULL");
   }

  }

}

7 调试分析

7.1 0:-1:59问题

在计时器功能里,倒数时间显示在terminal终端,但是在计时结束的时候显示的不是0 : 0 : 0,而是0 : -1 : 59。后来找其中的原因,发现是因为:

计时函数使用的是do-while循环,即先输出计时数字,再判断是否计时结束。这样会导致每次计时都会多输出一秒,也就是0 : 0 : 0的下一秒,0 : -1 : 59。

解决办法是避免最后一轮额外循环的输出,用一个判断语句进行限定:if(goalMinute-currentMinute >= 0){}

在这里插入图片描述

图6-1 0:-1:59问题

在这里插入图片描述

图6-2 修复后的效果

7.2 菜单条的颜色问题

在换肤功能中,功能的实现原理是改变背景颜色。对于标签、按钮来说,使用setBackground()方法即可实现,但是菜单条却不行。虽然菜单条的颜色不是很影响皮肤效果,但是若能该变,显示效果会更好。于是我在网上寻找解决办法,有的说必须重载void paintComponent(Graphics G)方法、有的说可以使用setBackground()但是都不合适,最终有一位网友提到了这个方法,特别有效getComponent().setBackground()于是这个问题就被顺利解决了。

7.3 时差问题

在计时器功能里,为使时间同步,需要调用System.currentTimeMillis()方法获取当前毫秒数,然后对其进行解析,方法如下:

currentTime = currentTime / 1000;

currentSecond = (int) (currentTime % 60);      // 获得第二

currentTime = currentTime / 60;

currentMinute = (int) (currentTime % 60);        // 获取分钟

currentTime = currentTime / 60;   

currentHour = (int) (currentTime % 24);       // 获取小时数

但是,据此得到的小时数却有问题,经过几轮调试后发现,总是与当前时间相差8个小时。后来听过思考,应该是因为北京时间处于东八区,而获取的时间是标准时间。解决办法是将用户输入的时间减去8,换算成标准时间再使用。

7.4 功能补充

如果有时间的话,应当再添加一个可以让用户自定义日期提醒的功能,这样用户就可以添加生日、会议等自定义事项,人机交互更加自由。

还要有登录功能,搭配数据库,可以实时保存用户自定义提醒事项和闹钟的数据。

8 测试结果

8.1 跳转功能

Fuction菜单下有闹钟、跳转、上一年、下一年、上个月、下个月等功能。测试Function菜单下的跳转功能,跳转到2023年10月1日。

在这里插入图片描述

图8-1 跳转前,窗口输入

在这里插入图片描述

图8-2 跳转后,日期改变

8.2 换肤功能

测试菜单下的皮肤功能。

有安静的白色、柔和黄色、纯黑色、黄昏的深色四种皮肤可选,选择黄昏的深色和纯黑色进行测试。

在这里插入图片描述

图8-3 黄昏的深色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SdU5BqAf-1688105247808)(images/image-20230630140039785.png)]

图8-4 纯黑色

8.3 定时功能

测试功能菜单下的闹钟功能。当前时间20:53, 定一个闹钟,20:53提醒。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XgtQTU0z-1688105247809)(images/image-20230630140059539.png)]

图8-5 定时前,窗口输入

在这里插入图片描述

图8-6 运行时,终端显示倒计时

在这里插入图片描述

图8-7 时间到,显示时间到!

8.4 显示关于

帮助菜单提供关于开发者的一些信息。其中自述文件显示软件的使用说明、关于显示开发者的个人信息。

测试帮助菜单下的关于提示

在这里插入图片描述

图8-8 关于开发者

9 总结与展望

通过这次课程设计,加深了我们对面向对象程序设计的理论、方法和基础知识的理解,同时我们也掌握使用Java语言进行面向对象设计的基本方法,并且提高运用面向对象知识分析实际问题、解决实际问题的能力。更进一步地认识到在Java语言中不可以任意实现内部类对外部类中的变量的访问,除非为final型,另外,在编写程序的过程中,对java编译器的使用也是必不可少的,他可以帮助我们更迅速更直观的知道很多的类与对应的方法,如Canlender中的getInstance方法,该方法返回一个Calendar对象,其日历字段已由当前日期和时间初始化,以及大量的add和set方法的使用。在以后的时间里我们会利用课余时间来继续学习Java语言,争取能够较好地掌握它并且能够达到运用自如的境界。这次课程设计,使我对本门课程有了更深一步的理解,《JAVA程序设计》并不是简单的计算机语言,它能够延伸到更宽更广的领域。
资源链接:基于Java的万年历(课设)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/33367.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 2501 数组中最长的方波 Java

方法一&#xff0c;哈希表枚举 构造哈希集合&#xff0c;记录出现过的数字枚举遍历 import java.util.HashSet; import java.util.Set;class Solution {public int longestSquareStreak(int[] nums) {//构造哈希表集合&#xff0c;记录出现过的数字&#xff0c;转long型&…

如何在Microsoft Excel中迅速冻结首行和末行

如果你正在处理一个大型电子表格&#xff0c;那么冻结某些行或列会很有用&#xff0c;这样当你滚动浏览工作表的其余部分时&#xff0c;它们会留在屏幕上。 当你在 Excel 中滚动浏览大的工作表时&#xff0c;你可能希望保留一些行或列&#xff0c;例如页眉。Excel 允许你通过以…

2023年华中杯数学建模B题小学数学应用题相似性度量及难度评估解题全过程文档及程序

2023年华中杯数学建模 B题 小学数学应用题相似性度量及难度评估 原题再现 某 MOOC 在线教育平台希望能够进行个性化教学&#xff0c;实现用户自主学习。在用户学习时&#xff0c;系统从题库中随机抽取若干道与例题同步的随堂测试题&#xff0c;记录、分析学生的学习和答题信息…

网络安全实战植入后门程序

在 VMware 上建立两个虚拟机&#xff1a;win7 和 kali。 Kali&#xff1a;它是 Linux 发行版的操作系统&#xff0c;它拥有超过 300 个渗透测试工具&#xff0c;就不用自己再去找安装包&#xff0c;去安装到我们自己的电脑上了&#xff0c;毕竟自己从网上找到&#xff0c;也不…

前端Vue自定义轮播图swiper 轮播图dot 轮播图指示indicate

前端Vue自定义轮播图swiper 轮播图dot 轮播图指示indicate&#xff0c;下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13193 效果图如下: ​ 编辑切换为居中 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; ​…

【HTTP 协议1】图文详解 HTTP 请求和应答报文

文章目录 前言一、认识 HTTP 协议1, 什么是 HTTP 协议2, HTTP 协议的报文格式 二、HTTP 请求报文1, 认识方法1.1, GET 和 POST 辨析(重点)1.2, 其他方法 2, 认识 URL3, 认识 Header3.1, Host3.2, Content-Length3.3 Content-Type3.4, User-Agent3.5, Referer3.6, Cookie(重点) …

【C#】并行编程实战:任务并行性(下)

本教程对应学习工程&#xff1a;魔术师Dix / HandsOnParallelProgramming GitCode 本章继续介绍任务并行性&#xff0c;因篇幅所限&#xff0c;本章为下篇。 6、处理任务异常 所有优秀的程序员都擅长高效地处理异常&#xff0c;这也是并行编程最重要的方面之一。任务并…

JMeter请求头添加删除方法(解决请求头类型冲突)

JMeter请求头添加删除方法&#xff08;解决请求头类型冲突&#xff09; 1. 为什么会有冲突 请求头的Content-Type类型在做上传和请求图片地址是&#xff0c;请求头类型是不一样的 请求图片地址&#xff1a;Content-Type: image/jpeg 一般的Restful接口&#xff1a;Content-Ty…

SpringBoot整合logback日志框架详解(提供Gitee源码)

前言&#xff1a;本篇博客主要介绍如何把主流的日志框架快速整合到目前的SpringBoot框架中&#xff0c;对六种日志等级进行介绍以及使用方法。 目录 一、日志级别 1、TRACE 2、DEBUG 3、INFO 4、WARN 5、ERROR 6、FATAL 二、导入pom.xml依赖 三、application.yml配置…

JS 1.如何实现继承 2.原型和原型链

1_使用class实现继承 /** 继承 */ class Person { constructor(name) { this.name name;}drink() { console.log(喝水)} }class Student extends Person{ constructor(name, score) { // new Personsuper(name);this.score score;}introduce() { console.log(我是${this.nam…

RISCV Reader笔记_4 乘除,浮点扩展

乘法和除法指令 前面了解过 RV32I不带乘除。扩展的RV32M里面有。 mul 较简单。div 是商&#xff0c;rem 是余数。 指令格式都差不多&#xff0c;基本就是靠 func 码确定变体。 因为两个32位数乘积是64位数&#xff0c;一条指令处理会比较复杂&#xff0c;因此分为两个指令计算…

vue+css中通过一个div的hover触发另一个的样式变化

思路 通过触发父div&#xff0c;除了改变父div的背景色外&#xff0c;还同时改变div中i标签的颜色 效果图 原本 hover触发后 html代码 <div class"user_addfrid"><i class"iconfont icon-friend-add"></i> </div> css代码 …

使用Xshell服务器跑程序,用pycharm连接服务器远程开发

目标&#xff1a; 1.使用Xshell在服务器上创建自己项目需要的虚拟环境 2.用pycharm实现远程服务器的连接&#xff08;这样就可以在本地debug或者写代码&#xff0c;然后再用xshell在服务器上跑&#xff09; 一、使用Xshell在服务器上创建自己项目需要的虚拟环境 1.打开Xshe…

LangChain-Agent自定义Tools类 ——输入参数篇(二)

给自定义函数传入输入参数&#xff0c;分别有single-input 参数函数案例和multi-input 参数函数案例&#xff1a; from langchain.agents import Tool from langchain.tools import BaseTool from math import pi from typing import Union from math import pi from typing …

利用nginx/apache代理wss 实现 小程序 端口 反向代理

除了用Workerman自身的SSL&#xff0c;也可以利用nginx/apache作为wss代理转发给workerman 我就是栽在这大坑里&#xff08;nginx/apache代理wss&#xff0c;workerman部分就不要设置ssl&#xff0c;否则将无法连接&#xff0c;两个方法2选1&#xff09;官方推荐用nginx/apach…

Oracle VM VirtualBox添加磁盘

文章目录 1、Oracle VM VirtualBox添加磁盘 1、Oracle VM VirtualBox添加磁盘 1.关闭正在启动的Oracle VM VirtualBox 2、选择存储 3、点击最右边 4、选择创建 直接下一步&#xff1a; 直接下一步&#xff1a; 调整需要的大小–创建即可: 此时此刻磁盘加载成功&#xff0…

如何预防DDOS和CC攻击

在当今数字化世界中&#xff0c;网络安全成为各行各业亟需解决的重要问题。最近&#xff0c;由于DDoS&#xff08;分布式拒绝服务&#xff09;和CC&#xff08;恶意咨询&#xff09;攻击事件的频繁发生&#xff0c;网络安全进一步引起了人们的关注。 据可靠消息源透露&#xff…

浅入浅出Java锁

前提 做分布式爬虫时&#xff0c;结合已有的架构&#xff0c;直接对某网站的详情页进行了爬取&#xff1b;尴尬的是&#xff0c;某网站需先采集列表页&#xff0c;之后才能采集详情页&#xff1b;这种防爬手段使用了用户行为监控&#xff0c;行为异常的访问直接就给屏蔽了。 对…

445端口是啥?445端口怎么关闭?

445端口是Windows系统中的SMB协议&#xff0c;用于文件共享和网络打印功能。然而&#xff0c;这个端口也是黑客攻击的重要入口之一。那么&#xff0c;如何关闭445端口&#xff0c;保护自己的计算机安全呢&#xff1f; 关闭445端口的方法 1.在“控制面板”中打开“管理员工具”…

亚马逊云科技通过“逆向工作法”,为客户解决数据库问题

最近,数据库领域发生了一个大事件,可以称得上是一座里程碑。全球最具权威的IT研究公司Gartner最近发布了一个消息:在2022年的全球DBMS市场份额中,亚马逊云科技的数据库超越微软,登顶第一。 亚马逊云科技、微软、Oracle这三巨头近几年一直排名前三,占据了全球DBMS超过三分之二的…
最新文章