画出一个时钟

感谢wqjsir这位博主代码的帮助,虽然他的那个闹钟的代码我基本看不懂啦,但是还是学习到了很多的思路。后来自己写了一个,只要添加上包名就可以运行了!注释也加得很详细,只要对线程、Graphics2D、GeneralPath、Math类、Calendar类有些理解就可以看懂了。希望能够帮助到各位!


//添加包名就可以运行

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class ClockTest extends JPanel implements Runnable
{
/**

*/
private static final long serialVersionUID = 1L ;
JFrame frame ;
int width = 430 ;
int height = 430 ;//窗口的宽高
double j = 0 ;//j在线程中每秒增加1

public ClockTest () 
{
getPreferredTime () ;//获取当前的时间
frameSet () ;//设置窗口
}


public void paintComponent(Graphics g)//重写JPanel的paintComponent方法
{
super.paintComponent(g) ;
Graphics2D g2d = (Graphics2D)g ;//把Graphics的画笔g转换成功能更强大的Graphics2D笔
g2d.translate(width/2,height/2) ;//把画笔的画图起点变成整个窗口的中间点
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) ;//抗锯齿 
paintMinuteDot (g2d) ;//画出分钟点
paintHourPointer (g2d) ;//画时针
paintMinutePointer (g2d) ;//画分针
paintSecondPointer (g2d) ;//画秒针
}

public void getPreferredTime ()//获取当前的时间
{
Calendar calendar = Calendar.getInstance() ;
double sec = calendar.get(Calendar.SECOND) ;
double min = calendar.get(Calendar.MINUTE)*60 ;
double hou = calendar.get(Calendar.HOUR)*3600 ;//12小时制
j = sec + min + hou ;//获取当前的秒数,因为画的三支针都是按照秒数进行计算。
}

public void frameSet ()
{
frame = new JFrame () ;
frame.add(this) ;
frame.setSize(new Dimension(442,476)) ;//窗口的大小会大一点
frame.setVisible(true) ;
}

public void run ()
{
while(true)
{
try 
{
Thread.sleep(1000) ;//每秒j增加1
j += 1 ;
if(j==43200)//当j等于43200秒时,也就是0点0时0分时,j变成0,否则j会不断增大
{
j = 0 ;
}
repaint () ;//重绘

catch (InterruptedException e) 
{
e.printStackTrace() ;
}
}
}


public void paintMinuteDot (Graphics2D g2d)//画分针点
{
Color col = Color.BLACK ;
Ellipse2D point2d = null ;
double x = 0 ;
double y = 0 ;
for(double i = 0 ; i < 60 ; i ++)
{
double angle = i*6-90 ;//因为画笔原点变了,这里是从(0,-200)这个点开始画,每隔6°画一个圆
double pos[] = calculatePointer(angle) ;//计算角度的位置
x = 200*pos [0] ;
y = 200*pos [1] ; //计算角度的位置
if(i%5==0)//第5个第10个点以此类推用红笔画
{
col = Color.RED ;
point2d = new Ellipse2D.Double(x-6.5,y-6.5,13,13) ;
/*6.5是圆的半径13除以2得出的,减6.5的原因是:圆是由左上角坐标和长宽画出的正方形的内接圆,减去这个数,才是这个圆的圆心所在
* 而秒针应该正指所有圆的圆心。*/
}
else
{
col = Color.BLACK ;
point2d = new Ellipse2D.Double(x-5,y-5,10,10) ;//不是5的倍数的点用黑色笔画,大小会小
}
g2d.setColor(col) ;
g2d.fill(point2d) ;//填充方法
  }
}

public void paintSecondPointer (Graphics2D g2d)//画秒针
{
double angle = j*6-90 ;//得出当前角度
double pos [] = calculatePointer (angle) ;//得出当前位置
Line2D l2d = new Line2D.Double(0,0,190*pos[0],190*pos[1]) ;//得出当前位置
g2d.setColor(Color.BLACK) ;
g2d.draw(l2d) ;//用黑笔画
}

public void paintMinutePointer (Graphics2D g2d)//画分针
{
int id = 1 ;//id用来标识这个究竟是分针还是时针,因为只为这两支针添加了额外的shape
double angle = j*1/10-90 ;//得出当前角度
g2d.setColor(Color.RED) ;//用红笔画
g2d.fill(paintPointerShape (calculatePointer (angle),id)) ;
/*calculPointer得出当前角度的分针应该在的位置(还没有乘倍数)然后把这个位置传给paintPointerShape,让这个方法得出一个GeneralPath
*即“通用路径”,这个通用路径会连接出一个闭合图形,然后用画笔的fill方法填充这个闭合图形
*/
}

public void paintHourPointer (Graphics2D g2d)//画是真
{
int id = 0 ;//时针id
double angle = j*1/120-90 ;//得出当前角度
g2d.setColor(Color.GRAY) ;//用灰色笔画
g2d.fill(paintPointerShape (calculatePointer (angle),id)) ;
/*calculPointer得出当前角度的分针应该在的位置(还没有乘倍数)然后把这个位置传给paintPointerShape,让这个方法得出一个GeneralPath
*即“通用路径”,这个通用路径会连接出一个闭合图形,然后用画笔的fill方法填充这个闭合图形
*/
}

public double [] calculatePointer (double angle)//计算当前位置(没有乘倍数的位置)
{
double radian = Math.toRadians(angle) ;//把角度变弧度
double pos [] = {Math.cos(radian),Math.sin(radian)} ;//计算cos和sin,得出来的是倍数为1时的位置
return pos ; //返回一个double数组
}

public GeneralPath paintPointerShape (double pos [],int id)//画时针分针的形状
{
GeneralPath gp = new GeneralPath () ;//“通用路径”,用以连接几个点以构成闭合图形
double x , y , x2 , y2 , x3 , y3 , x4 , y4 , point1 = 0 , point2 = 0 , point4 = 0 , angle = 0 ;
if(id==0)//如果传进来的id为0,即时针,倍数的值和除数(角度)的值会不同
{
point1 = 100 ;
point2 = 10 ;
point4 = 20 ;
angle = 120 ;
}
else//如果传进来的id为1,即分针,倍数的值和除数(角度)的值会不同
{
point1 = 150 ;
point2 = 5 ;
point4 = 10  ;
angle = 10 ;
}

x = point1*pos[0] ;
y = point1*pos[1] ;
Point2D p2d = new Point2D.Double(x,y) ;//第一个点

double [] pos2 = calculatePointer(j*1/angle-180) ;
x2 = point2*pos2[0] ;
y2 = point2*pos2[1] ;
Point2D p2d2 = new Point2D.Double(x2,y2) ;//经过calculatePointer的计算并且乘于倍数之后得出第二个点

x3 = -x2 ;
y3 = -y2 ;
Point2D p2d3 = new Point2D.Double(x3,y3) ;//第三个点为第二个点的对称点

double [] pos4 = calculatePointer(j*1/angle+90) ;
x4 = point4*pos4[0] ;
y4 = point4*pos4[1] ;
Point2D p2d4 = new Point2D.Double(x4,y4) ;//经过calculatePointer的计算并且乘于倍数之后得出第四个点,注意角度不同

gp.append(new Line2D.Double(p2d,p2d2), true) ;
gp.append(new Line2D.Double(p2d2,p2d4), true) ;
gp.append(new Line2D.Double(p2d4,p2d3), true) ;
gp.append(new Line2D.Double(p2d3,p2d), true) ;//把四个点以一定顺序通过线连接起来,然后追加到“通用路径”中
return gp ;//返回一个“通用路径”,画笔的fill方法可以直接填充这个“通用路径”构造出的闭合图形
}

public static void main(String[] args) 
{
// TODO Auto-generated method stub
Thread th = new Thread (new ClockTest ()) ;
th.start() ;//开始线程
}

}

以下为预览图




此外,放上该君的博客,要多谢他~

http://blog.csdn.net/wqjsir/article/details/6097297

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值