使用Swing绘制动态时钟
本文实例为大家分享了利用Swing绘制一个动态时钟的具体代码,供大家参考,具体内容如下
效果
代码在下面,可跳过解析。
前言
编程实现一个时钟
利用Swing绘制一个时钟,只能是静态的。利用Calendar类获取当前的时分秒,然后根据数学公式绘制相应的时钟就可以了。
如果静态的时钟已经足够你使用,那么就无须用到线程的概念。
如何让时钟“动起来”
当然了,动起来肯定是不可能的,但是我们可以利用人眼的视觉,让时钟“好像动起来”,其实着很简单,只要让当前的图像每隔一秒种刷新一次就可以了。这样秒针在动,数字时间也在动,整个时钟就好像“动起来了”
线程
利用线程实现刷新,刷新间隔是1秒,每次刷新都先生成当前的时间,然后JVM又会自动调用paintComponent方法绘制图形,这样就好像时钟动起来了。
Threadthread=newThread(){
publicvoidrun(){
while(true){
StillClockclock=newStillClock();
MessagePanelmessagePanel1=newMessagePanel(clock.getHour()+":"+
clock.getMinute()+":"+clock.getSecond());
//设置显示居中
messagePanel1.setCentered(true);
//设置前景颜色
messagePanel1.setForeground(Color.black);
//设置字体
messagePanel1.setFont(newFont("Courier",Font.BOLD,16));
add(clock);
add(messagePanel1,BorderLayout.SOUTH);
clock.setVisible(true);
validate();//接下来会每隔一秒重绘一次时钟——即(从frame中将clock组件删除),因此调用validate方法,使容器重新布置其子组件
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
clock.setVisible(false);
remove(clock);//在父容器中将其删除
clock.invalidate();//使容器失效
}
}
};
thread.start();
线程代码解析
Threadthread=newThread(){};
注意结尾使用了分号,既然使用了线程,那么需要重写它的run方法:
publicvoidrun(){}
既然想让时钟一直动起来,那么死循环是最好的选择
while(true){}
在while里面,每次都先生成当前的时间:
StillClockclock=newStillClock();
这里生成了一个无参构造的StillClock类,StillClock的无参构造方法里面会自动生成当前的时间。
注意:这里的StillClock是我自己定义的,代码贴在后面,但是如果不关心他是怎么实现的,可以直接忽略原理,直接使用,包括代码里面的messagePanel也是一样的自定义类。
时间生成完了之后,把时钟图形、当前时间的字符串、布局位置利用add()方法绘制到屏幕上
add(clock); add(messagePanel1,BorderLayout.SOUTH);
接下来会每隔一秒重绘一次时钟——即(从frame中将clock组件删除),因此调用validate方法,使容器重新布置其子组件。
thread.start();
让线程开始工作把。
完整代码
DisplayClock.java:
packageTest;
importjavax.swing.*;
importjavax.swing.border.Border;
importjava.awt.*;
publicclassDisplayClockextendsJFrame{
publicDisplayClock(){
//创建一个现在的时间
StillClockclock=newStillClock();
//获取当前的时间
clock.setCurrentTime();
//设置时间的显示格式
Threadthread=newThread(){
publicvoidrun(){
while(true){
StillClockclock=newStillClock();
MessagePanelmessagePanel1=newMessagePanel(clock.getHour()+":"+
clock.getMinute()+":"+clock.getSecond());
//设置显示居中
messagePanel1.setCentered(true);
//设置前景颜色
messagePanel1.setForeground(Color.black);
//设置字体
messagePanel1.setFont(newFont("Courier",Font.BOLD,16));
add(clock);
add(messagePanel1,BorderLayout.SOUTH);
clock.setVisible(true);
validate();//接下来会每隔一秒重绘一次时钟——即(从frame中将clock组件删除),因此调用validate方法,使容器重新布置其子组件
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
clock.setVisible(false);
remove(clock);//在父容器中将其删除
clock.invalidate();//使容器失效
}
}
};
thread.start();
//布局默认为BorderLayout,让显示信息在底部(即南边)
}
publicstaticvoidmain(String[]args){
DisplayClockframe=newDisplayClock();
frame.setTitle("DisplayClock");
frame.setSize(300,350);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
StillClock.java:
packageTest;
importsun.util.calendar.Gregorian;
importjavax.swing.*;
importjava.awt.*;
importjava.util.Calendar;
importjava.util.GregorianCalendar;
publicclassStillClockextendsJPanel{
publicintgetHour(){
returnhour;
}
publicvoidsetHour(inthour){
this.hour=hour;
repaint();
}
publicintgetMinute(){
returnminute;
}
publicvoidsetMinute(intminute){
this.minute=minute;
repaint();
}
publicintgetSecond(){
returnsecond;
}
publicvoidsetSecond(intsecond){
this.second=second;
repaint();
}
privateinthour;
privateintminute;
privateintsecond;
publicStillClock(){
setCurrentTime();
}
publicStillClock(inthour,intminute,intsecond){
this.hour=hour;
this.minute=minute;
this.second=second;
}
//使用Graphics类绘制图形,需要重写paintComponent方法
@Override
protectedvoidpaintComponent(Graphicsg){
super.paintComponent(g);
//绘制时钟参数
intclockRadius=(int)(Math.min(getWidth(),getHeight())*0.8*0.5);
intxCenter=getWidth()/2;
intyCenter=getHeight()/2;
//绘制一个圆
g.setColor(Color.BLACK);
g.drawOval(xCenter-clockRadius,yCenter-clockRadius,2*clockRadius
,2*clockRadius);
g.drawString("12",xCenter-5,yCenter-clockRadius+12);
g.drawString("9",xCenter-clockRadius+3,yCenter+5);
g.drawString("3",xCenter+clockRadius-10,yCenter
+3);
g.drawString("6",xCenter-3,yCenter+clockRadius-3);
//绘制秒针
intsLength=(int)(clockRadius*0.8);
intxSecond=(int)(xCenter+sLength*Math.sin(second*(2*Math.PI/60)));
intySecond=(int)(xCenter-sLength*Math.cos(second*(2*Math.PI/60)));
g.setColor(Color.red);
g.drawLine(xCenter,yCenter,xSecond,ySecond);
//绘制分针
intmLength=(int)(clockRadius*0.65);
intxMinute=(int)(xCenter+mLength*Math.sin(minute*(2*Math.PI/60)));
intyMinute=(int)(xCenter-mLength*Math.cos(minute*(2*Math.PI/60)));
g.setColor(Color.blue);
g.drawLine(xCenter,yCenter,xMinute,yMinute);
//绘制时针
inthLength=(int)(clockRadius*0.5);
intxHour=(int)(xCenter+hLength*Math.sin((hour%12+minute/60.0)*(2*Math.PI/12)));
intyHour=(int)(xCenter-hLength*Math.cos((hour%12+minute/60.0)*(2*Math.PI/12)));
g.setColor(Color.green);
g.drawLine(xCenter,yCenter,xHour,yHour);
}
publicvoidsetCurrentTime(){
//构造一个日历类设定当前日期和时间
Calendarcalendar=newGregorianCalendar();
//设定时分秒
this.hour=calendar.get(Calendar.HOUR_OF_DAY);
this.minute=calendar.get(Calendar.MINUTE);
this.second=calendar.get(Calendar.SECOND);
}
publicDimensiongetPreferredSize(){
returnnewDimension(200,200);
}
}
messagePanel:
packageTest;
importjavax.swing.*;
importjava.awt.*;
publicclassMessagePanelextendsJPanel{
//显示的信息
privateStringmessage="Welcometojava";
//显示信息x的坐标
privateintxCoordinate=20;
//显示信息y的坐标
privateintyCoordinate=20;
//信息是否被显示在中心部位
privatebooleancentered;
//水平和垂直的移动显示信息
privateintinterval=10;
publicintgetXCoordinate(){
returnxCoordinate;
}
publicvoidsetXCoordinate(intxCoordinate){
this.xCoordinate=xCoordinate;
repaint();
}
//无参构造
publicMessagePanel(){
}
//带参构造
publicMessagePanel(Stringmessage){
this.message=message;
repaint();
}
publicintgetYCoordinate(){
returnyCoordinate;
}
publicvoidsetYCoordinate(intyCoordinate){
this.yCoordinate=yCoordinate;
repaint();
}
publicbooleanisCentered(){
returncentered;
}
publicvoidsetCentered(booleancentered){
this.centered=centered;
repaint();
}
publicintgetInterval(){
returninterval;
}
publicvoidsetInterval(intinterval){
this.interval=interval;
repaint();
}
@Override
protectedvoidpaintComponent(Graphicsg){
super.paintComponent(g);
if(centered){
//设定字体
FontMetricsfm=g.getFontMetrics();
//设置显示字体
intstringWidth=fm.stringWidth(message);
intstringAscent=fm.getAscent();
xCoordinate=getWidth()/2-stringWidth/2;
yCoordinate=getHeight()/2+stringAscent/2;
}
g.drawString(message,xCoordinate,yCoordinate);
}
//让信息往左边移动
publicvoidmoveLeft(){
xCoordinate-=interval;
repaint();
}
//让信息往右边移动
publicvoidmoveRight(){
xCoordinate+=interval;
repaint();
}
//让信息向上移动
publicvoidmoveUp(){
yCoordinate+=interval;
repaint();
}
publicvoidmoveDown(){
yCoordinate-=interval;
repaint();
}
//固定写法,不必探究
@Override
publicDimensiongetPreferredSize(){
returnnewDimension(200,30);
}
}
结束
写的有些粗糙,有需要的可以根据自己的需求进行更改,比如如何更加稳定的实现动态时钟,让时钟刻度更加精细(根据数学公式增加刻度线即可),希望可以帮助到你。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。