java课程设计--模拟时钟.docx
目录(模拟时钟)第1章课题简述21.1 课题的目的21.2 课题的要求21.2.1 运行的窗口界面的要求21.2.2 程序实现的功能要求2第2章设计思路展示22.1 整个程序的模块结构及流程22.2 实现可显示窗口界面32.3 通过多线程重绘界面32.4 重写paint(GraphicsG)方法32.4.1绘制表盘32.4.2获取系统时间42.4.3绘制指针并显示具体时间42. 4.4增加功能5第3章程序功能的实现62.1 主函数的实现62.2 主要功能模块的实现63. 2.1使用多线程重绘界面63. 2.2获取系统时间并绘制时钟界面7第4章调试及发现问题的解决11第5章程序测试及分析12第6章总结13参考文献14第1章课题简述本次编程语言基础课程设计的题目是设计模拟时钟。1.1 课题的目的模拟时钟是日常生活中所必须的工具。在各种环境下,比如晨起、上下班、各种考试,人们常常需要指示时间的工具,以合理分配时间,达到按时或者及时完成工作或者学习任务的目的,帮助用户实现时间最合理的使用。因此这类工具通过java、C语言等编程语言直接实现具有较大的实际意义。通过模拟时钟课程设计课题的实现,掌握并熟练使用java编程语言的多线程技术,以及GUl技术和日期时间类的使用。为日后的专业课学习打好基础,做好充足准备。1.2 课题的要求1.2.1 运行的窗口界面的要求(1)在窗口绘制表盘和指针指示时间点和其变化。(2)在窗口用数字表显示时间点及其变化。(3)在窗口显示系统日期,包括年月日、上下午和星期。(4)界面显示要美观、简洁易懂,便于用户使用,和获取其需要的相应的时间日期信息。1.2.2 程序实现的功能要求本课题要求通过多线程以每秒的间隔重绘窗口界面,获取系统时间,不断更新显示在窗口界面,以时刻正确指示用户系统时间。Cchongxipaint(Graphicsg)第2章设计思路展示2.1 整个程序的模块结构及流程根据课题要求,整个程序需要一个可显示的窗口界面,在界面上显示不断更新的系统时间。系统时间的显示需要表盘及指针和数字显示,界面重绘和更新通过多线程实现,接下来获取系统时间并重写paint(Graphicsg)将系统时间显示在窗口界面上。窗口界面模拟时钟数字时钟图2-1程序界面结构图2.2 实现可显示窗口界面由于用户需要在程序一次运行后能够不断获取相应时间日期信息,也就是说,这个运行结果要始终保留给用户,所以可以通过一个可视化的窗口把信息呈现给用户。这个可视化的窗口要求可以显示给用户,它应该有美观的外观,简洁的图形元素,相应的信息输出。一般情况下,用户需要对窗口进行指示,比如调整窗口大小,使得窗口显示或者隐藏,这都需要程序员事先考虑到并通过代码来实现符合用户需要的这些各项功能,以便用户实现。2.3 3通过多线程重绘界面根据课题要求,创建模拟时钟小程序,需要按照固定的时间间隔更新窗口信息,比如时间元素里的秒需要按照一秒的时间间隔去更新,分钟按照60秒的时间间隔去更新,小时按照3600秒的时间间隔去更新,年月日、上下午等需要更长的时间间隔去更新,实现窗口界面的重绘需要用到多线程,选取所有时间间隔的最小值作为重绘界面的休眠值。如,语句Thread.sleep(1000);2. 4重写paint(Graphicsg)方法2.4. 1绘制表盘根据课题要求,模拟时钟的内容要求包括通过模拟时钟显示时间信息。市面上的模拟时钟有不同的外边框,包括矩形、方形和各种动物轮廓形,这里选取标准圆作为模拟时钟的外边框,原因为圆为时钟的传统外边框,具有线条流畅、表现时间点更为直观等特色。外边框由均匀分布的粉色和灰色小圆点组成,这里所有原点不止形成圆形的外观组合,由于其均匀分布在圆内,还能表示时钟上指示时间的60个点,所有原点由48个粉色单色点和12个粉灰双色点组成。表盘除了指示时间的点外,按照表盘外观,圆,的元素特色,特地在圆心处添加了字符串“Karry”,增强可视行与美观性。为了完成圆的绘制,需要获得窗口的高度和宽度,以此作为表盘绘制的参数,以便表盘大小尺寸与窗口大小尺寸相协调。同时创建两个成员变量rl,r2接收这两个参数,代码为rl=getSize().Width/2-40;r2=getSize().height2-T-40;具体如图2-3所示。指针的绘制将在获取时间后实现。karry图2-1模拟时钟的表盘初步展示2.4.2获取系统时间完成模拟时钟小程序必不可少的是获取系统时间,这就要用到时间和日期类Calendar及其子类GregorianCalendar,通过类名创建Calendar对象指向其子类GregorianCalendar,具体代码为:Calendartime=newGregorianCalendar();那么就可以通过对象名"time"调用Calendar类及其子类GregorianCa1endar的内部方法,若要使用类中特有字段,由于字段的定义为“static”,可以通过类名使用,比如通过使用Calendar类中特有字段和其内部方法get()获取时间元素中“分钟”这个时间元素,可以使用以下语句:intminute=time,get(Calendar.MINUTE);GregorianCalendar类相对于Calendar类新增了字段和方法,以便对时间日期进行操作。2.4.3 绘制指针并用显示具体时间指针用来指示时间的变化,要根据具体时间来绘制,所以再获取系统时间之后绘制指针。指针包括时针、分针和秒针。根据习惯,时针、分针、秒针的长度依次增长、宽度依次减小,所以再绘制指示不同时间元素的指针的时候都需要重新设置画笔的属性,比如绘制时针时,画笔的设置为g2D.setstroke(newBasicStroke(2.5f);而绘制分针时画笔设置为g2D.SetStroke(newBasicStroke(2.Of);但是对于指针不同的长度绘制,要通过画笔绘线的始末坐标差异来完成,具体再3.2.2获取系统时间并绘制时钟界面这一章节讲解。2.4.4 增加功能为了使用户在获取时间信息的同时也获得具体日期信息,在窗口里同时显示了年月日信息,包括用英文显示的星期信息。第3章程序功能的实现3.1主函数的实现在主函数实现之前,一方面需要定义X,y,x,y,rl,r2,sh,mh,hh和ang这些变量,以及常量浮点型常量RAD,同时初始化RAD,finaldoubleRAD=Math.PI180;完成角度和弧度的转换,方便设置指针转动的角度。另一方面为使用线程,需要创建线程对象ThreadCIoCk二null;接下进入主函数的实现,在主函数里完成窗口的属性设置。主要代码如下:publicsimulationclock()为窗口设置标题SUPer(模拟时钟);设置窗口的组件排列方式SetLayout(newFlowLayoutO);设置窗口的弹出位置和大小,因为要增强模拟时钟小窗口的特色,在小窗口上部添加了标签,所以增加了小窗口的高度,以便表盘以圆的轮廓显示。setBounds(100,100,400,420);添加标签Labelbutton=newLabeI("蜿蜒的,沿途一路曲折,有时候相信的,未必开花结果);add(button);begin();设置窗口关闭按钮可实现关闭事件addWindowListener(newWindowAdapterOpublicvoidWindowClosing(WindowEvente)System,exit(0););设置窗口可见SetVisible(true);3.2主要功能模块的实现3.2.1使用多线程重绘界面本次课题里使用多线程来控制程序运行进程,通过编写类Clock继承父类Frame的同时也继承接口Runnable,并实现其内部方法run(),在Clock内部通过类名Thread创建线程对象ClOCk,通过线程对象调用线程类内部方法Start(),从而启动线程,使得程序启动后运行。程序里相应语句为:publicclasssimulationclockextendsFrameimplementsRunnableThreadclock;publicsimulationclock()begin();创建无返回值的方法publicvoidbegin()if(clock=null)将自身线程对象作为参数传给其构造方法,获得新的线程值,赋值给线程clockclock=newThread(this);调用线程类内部方法start()启动线程clock,start();实现接口Runnable中run()publicvoidrun()如果线程值为空,重画界面while(clock!=null)重画界面repaint();由于方法sleep()的定义:publicstaticvoidsleep(longmillisecond)throwInterruptedException要把SIeeP()的调用放在try-catch语句里面捕获异常tryThread,sleep(100O);catch(InterruptedExceptione)e.PrintStackTrace();3.2.2获取系统时间并绘制时钟界面由于位于父类的父类的方法paint(Graphicsg)可以直接在窗口容器上绘制图形元素,获取系统时间并绘制时钟界面在重写的方法Paint(GraPhiCSg)中直接完成。publicvoidpaint(Graphicsg)使父类画笔Graphicsg强制转化成Graphics2Dg2DGraphics2Dg2D=(Graphics2D)g;绘制时钟表盘intL=insets,left2,T=insets,top/2;设置表盘的长宽标准rl=getSize().width2-L-40;r2=getSize().height2-T-40;设置表盘的圆心位置x0=rl+20+L+30;y0=r2+20+T+50;g.drawString(,zkarry,x0-10,y0+5);绘制时钟上的点绘制12数字,和对应的十二个点十二个数字或者圆点均匀分布在表盘上,因此把圆盘均分成十二个区域,每个区域所占弧度值为30;ang=30;for(inti=l;i<=12;i+)由于窗口容器坐标原点位置,在窗口左上角,当设置坐标X值为半径的sin值时要同时加上表盘的圆心的坐标x值X=(int)(rl-20)*Math.sin(RAD*ang)+x);当设置坐标y值为半径的cos值时要同时用表盘的圆心的坐标y值减去它y=(int)(y0-(r2-20)*Math.cos(RAD*ang);设置画笔属性,包括画笔粗细、画笔颜色g2D.SetStroke(newBasicStroke(4.Of);g.SetColor(Color,gray);画Srting类型的数字g.drawString(zzzz+i,x,y);画短线类型的原点g.drawLine(x,y,x,y-2);增加ang数据的类型,改变数字或者原点坐标ang+=30;绘制六十个点六十个圆点而匀分布在表盘上,因此把圆盘均分成六十个区域,每个区域所占弧度值为6;ang=6;for(intj=l;j<=60;j+)x=(int)(rl-20)*Math.sin(RAD*ang)÷x);y=(int)(y0-(r220)*Math.cos(RAD*ang);重新设置画笔属性g2D.setStroke(newBasicStroke(2.Of);g.setColor(Color.PINK);g.drawLine(x,y,x,y);ang+=6;)获取系统时间并根据系统时间绘制指针创建时间类对象time指向其子类Calendartime=newGregorianCalendar();获取不同时间字段intyear=time.get(GregorianCalendar.YEAR);intmonth=(time,get(Calendar.MONTH)+1);intday=time,get(Calendar.DAY_OF_MONTH);inthour=time,get(Calendar.HOUR_OF_DAY);intminute=time,get(Calendar.MINUTE);intsecond=time,get(Calendar.SECOND);在表盘上一秒所占的角度为6度intsh=second*6;一分钟所占的角度也是6度,在每分钟所占有的6度里,每秒有各占0.1度mh=minute*6+second10;一小时所占的角度是30度,在每小时所占有的30度里,每分钟有各占0.5度hh=hour*30+minute2;绘制指针,指针由表盘圆心指向圆点绘制秒针,秒针最长最细,X=(int)(rl*0.8*Math.sin(RAD*sh)+x);y=(int)(y0-r2*0.8*Math.cos(RAD*sh);g2D.SetStroke(newBasicStroke(1.5f);g.setColor(Color,pink);g.drawLine(xO,y,x,y);绘制分针x=(int)(rl*0.6*Math.sin(RAD*mh)+xO);y=(int)(y0-r2*0.6*Math.cos(RAD*mh);g2D.SetStroke(newBasicStroke(2.Of);g2D.SetBackground(Color,gray);g.setColor(Color,gray);g.drawLine(xO,y,x,y);绘制时针x=(int)(rl*O.4*Math.sin(RAD*hh)+x);y=(int)(y0-r2*0.4*Math.cos(RAD*hh);g2D.setStroke(newBasicStroke(2.5f);g.setColor(Color,pink);g.drawLine(xO,y,x,y);/在窗口显示其他时间元素其他时间元素可以看做字符串类型的图形元素绘制在窗口适当位置。StringSo=年+月+日;g2D.SetStroke(newBasicStroke(2.Of);g.setFont(newFont("Digital”,Font.PLAIN,20);g.SetColor(Color,gray);g.drawString(s,70,70);Stringsi;if(true)sl=year÷z,;if(month<10)Sl=Sl.+0+month+"elsesl=sl+month+“;if(day<10)sl=sl+"O"+day+”;ClSesl=sl+day+,z”;if(hour<=12)sl=sl+zz"+AM;CISesl=sl+zz"+"PM;g2D.SetStroke(newBasicStroke(2.Of);g.setFont(newFOnt("Digital”,Font.PLAIN,20);g.SetColor(Color,pink);g.drawString(si,20,70);Strings4=";if(hour<=9)s4+="0"+hour+”:"elses4+=hour+”:"if(minute<=9)s4+二0+IninUte+:;elses4+=minute+:;if(second<=9)s4+="0"+SeCOnd;elses4+=second;g.setFont(newFont("Digital”,Font.PLAIN,20);g.SetColor(Color,pink);g.drawString(s4,250,70);Strings2;if(true)s2=,Todayisthe;g.setFont(newFOnt("Digital”,Font.PLAIN,10);g.SetColor(Color,gray);g.drawString(s2,x0-30,y0+70);Strings3=null;switch(week)case1:s3=Sunday;break;case2:s3="Monday”;break;case3:s3="Tuesday;break;case 4: s3=,Wednesdayz,;break;case 5: s3=z*Tursdayzz;break;case 6: s3=z*Fridayz,;break;case 7: s3=z,Saturday,,;break;g. setFont(newFont("Digital”,Font.PLAIN,20);h. setColor(Color,pink);i. drawString(s3,x0-40,y0+100);第4章调试及发现问题的解决在程序编写过程中遇到了许多问题,去网上查找了相关资料,结合各种书籍才终于理解,但是在程序调试过程中,还是会有许多问题出现,来回修改代码,试过许多方法,完成了课题。具体问题及解决办法如下:1、弹出窗口小程序后,如何通过关闭按钮使用户直接关掉窗口?解决办法:对窗口添加窗口事件侦听。重写窗口事件适配器类的窗口关闭方法,使得窗口在用户点到关闭按钮时,能够正常关闭。2、如何通过线程控制程序运行?解决办法:因为在选择这个课程设计课题时,并没有接触到多线程,所以程序需要用到多线程,感觉很困惑,不知道怎样下手去实现线程控制进程。只能去把有关书籍研究几遍,再去看老师提供的线程教程视频,了解之后,程序才能继续往下编写。对于实现线程来控制程序运行,直接可以使类Clock继承接口RUnrIabIe,再在类内部,方法外部创建线程对象,通过对象名time调用线程内部类方法start(),启动线程,接下来重写run()方法,方法内部调用repaint。方法重绘界面。并设置线程休眠时间。3、如何根据将系统时间与指针关联?解决办法:当绘制好了表盘,根据固定时间点绘制指示时针就成了一个问题。首先需要指示秒数,这可以通过系统时间的秒值计算相应的角度,比如,秒数为1时,秒针与由圆心指向正北的线(根据地图约定俗成的上北下南)的夹角就是6度,秒数为30时,相应夹角就是180度。如果分针按照同样的原理绘制分针,那么就出现一个问题,比如2分30秒,指针只能指示秒针指示30秒,分针指示为2分整的位置,这显然不合理,于是应该考虑到指示分针的时候应该同时兼顾分钟值和秒数值,这就要把每分钟的度数根据总秒数在划分成均匀的角度,即每分钟所占的6度角再划分成均匀的60块,每秒占有0.1度,这样计算分针与由圆心指向正北的线的夹角就是:(分钟值*6+秒数*0.1)度;这样时针按同样原理来绘制,只需考虑到分钟值就好。4、如何将获取的星期值1、2、3、4、5、6和7转换成相应的英文表示获取系统时间值的星期值时,由于日期类提供的星期返回值为数字1、2、3、4、5、6和7,而我们需要的是星期的英文表示,所以需要将返回值转化了再绘制在窗口,于是可以CatCh语句,例如,当返回值为1是,执行语句:case1:s3="Sunday"break;只要将s3绘制在窗口。5、如何设置坐标?解决办法:由于各个字符所占用的像素无从得知,而无法设置两次绘制的字符串的间隔,我采用的解决办法就是一次一次更改坐标值,看调试结果后确定。第5章程序测试及分析运行程序,结果如图5-1。W的.沿途一路A折,有时候相信第,余必开花续累:*O工J平月口图5-1程序运行结果第6章总结经过三个双休的课程设计和许多零碎时间的调试程序,终于是完成了模拟小时钟的课题作业,这过程不仅学到许多新知识,也补充加深了对以前旧知识的理解,使得以后对java编程语言的应用更灵活,同时也提高自主解决问题的能力。总而言之,这次课程设计收获很大。总结下来有一下几点:1、遇到无从下手的困难的应对方法。当遇到遇到无从下手的困难时.,别颓废,别以为自己的课题就无法完成了,对各种知识深入是在解决问题中完成的,遇到困难越大,自身能力提升的空间就越大。可以通过查阅书籍,找寻各种相关视频还可以找老师帮助。2、自主学习能力的提局。独立完成课程设计可以很大程度提升自主学习能力。特别时当课题中设涉及未曾系统学习过的知识时,对于自主学习来讲,是一个很好的机会,因为这时候需要自己查找各种资源,不止,有了资源能否充分利用,能否借助手里的资源解决自己的问题都需要较好的自主学习能力,当跨过这些坎,学习能力或多或少都有提升。3、培养良好的编写程序的态度。完成任何一件事情,态度都是重要的,态度决定工作完成的好坏。编写程序需要极大的耐心,对于初学者来说,一个窗口小程序的完成并非易事,是意见需要花费时间的事。同时也需要细致谨慎,尽量少出差错,遇见提示的错误要立即解决,积攒下来,对于长代码来讲,要逐字逐句地浏览,得不偿失。4、编写程序的体会。编写程序是一件很有成就的事,当遇到许多困难,而这些困难在自己努力去解决终究得以解决时.,这时的成就感满满的。独立去完成一件从未尝试过的程序,那最初看起来很神奇的事在自己的小小努力下得以实现,这就是学习与创造的乐趣,而学习过程中只有这些乐趣能给学习注入源源不断的动力,进步在不知不觉中完成。但是比起同班里做更难题目的同学,深知自己还需要很大提升。程序的具体功能都己实现,但是在切换系统时,还有很多问题要处理,还需要在假期把这些知识补习了。对于程序员来说不止要了解编程语言知识,还需要了解编程环境。参考文献1袁海燕、王文涛.Java实用程序设计100例.北京:人民邮电出版社2宋波、李晋、李妙妍、张悦JaVa程序设计一基于JDK6和NetBeanS实现.北京:清华大学出版社