package unit14;
import javax.swing.*;
public class Example14_4 {
public static void main(String args[]){
JFrame jFrame=new JFrame();
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.add(new Clock());
jFrame.setSize(400,400);
}
}
package unit14;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.Date;
public class Clock extends Canvas implements ActionListener {
Line2D []second,minute,hour;
Timer secondTime;
Line2D s,m,h;
Date date;
int sindex,mindex,hindex;
Clock(){
secondTime = new Timer(1000,this);
//Timer(delay,new ActionListener()),1000单位毫秒,即每过一秒actionPerformed()执行一次
second=new Line2D[60];
minute=new Line2D[60];
hour=new Line2D[60];
second[0]=new Line2D.Double(0,0,0,-120);
minute[0]=new Line2D.Double(0,0,0,-100);
hour[0]=new Line2D.Double(0,0,0,-70);
for(int i=1;i<second.length;i++){
second[i]=new Line2D.Double(0,0,120*Math.sin(Math.PI*6*i/180),-120*Math.cos(Math.PI*6*i/180));
minute[i]=new Line2D.Double(0,0,100*Math.sin(Math.PI*6*i/180),-100*Math.cos(Math.PI*6*i/180));
hour[i]=new Line2D.Double(0,0,70*Math.sin(Math.PI*6*i/180),-70*Math.cos(Math.PI*6*i/180));
}
//指针偏移(只能写在这里,如果写在paint()里,则每repaint一次,它就会直线方向偏移一次
for(int i=0;i<second.length;i++){
second[i].setLine(120,120,second[i].getX2()+120,second[i].getY2()+120);
minute[i].setLine(120,120,minute[i].getX2()+120,minute[i].getY2()+120);
hour[i].setLine(120,120,hour[i].getX2()+120,hour[i].getY2()+120);
}
s=new Line2D.Double(0,0,0,0);
m=new Line2D.Double(0,0,0,0);
h=new Line2D.Double(0,0,0,0);
secondTime.start();
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g_2d=(Graphics2D)g;
Ellipse2D []ellipse2DS=new Ellipse2D[60];
//绘制表盘上的大刻度小刻度
g.setColor(Color.BLUE);
for(int i=0;i<ellipse2DS.length;i++){
if(i%5==0){
g.fillOval((int)(120*Math.cos(Math.PI*6*i/180)+120)-5,(int)(120*Math.sin(Math.PI*6*i/180)+120)-5,10,10);
}else{
g.fillOval((int)(120*Math.cos(Math.PI*6*i/180)+120)-2,(int)(120*Math.sin(Math.PI*6*i/180)+120)-2,4,4);
}
}
g.fillOval(112,112,16,16);
g_2d.setColor(Color.black);
g_2d.draw(s); 画线段只能用draw(),因为填充不了
BasicStroke bs=new BasicStroke(3,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL);
//第一个值为width,第二个值CAP值有CAP_BUTT,CAP_SQUARE,CAP_ROUND,第三个Join值表示当两条线段连接时,连接处的形状:JOIN_BUVEL,JOIN_MITER,JOIN_ROUND
g_2d.setStroke(bs);
g_2d.draw(m);
bs=new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
g_2d.setStroke(bs);
g_2d.draw(h);
}
public void actionPerformed(ActionEvent e){
if(e.getSource()==secondTime){
date=new Date(); //获得操作系统的当前时间
}
String str = date.toString();
//publid String substring(int beginIndex,int endIndex),beginIndex包括,endIndex不包括
sindex=Integer.parseInt(str.substring(17,19));//因为date()传回的数据类似于”2014-02-20 23:03:05”
mindex=Integer.parseInt(str.substring(14,16));
hindex=Integer.parseInt(str.substring(11,13))%12*5+mindex/12;
s.setLine(this.second[sindex]);
m.setLine(this.minute[mindex]);
h.setLine(this.hour[hindex]);
repaint();
}
}
以下是从网上找到的相关资料:
Canvas类的继承关系:Java.lang.Object->Android.graphics(图形类)->Canvas(画布类)
Graphics类以成员方法的形式封装了绘制各种图形的工具,而Graphics2D将绘制的所有图形用相应的类对象去标识。这是他们两个的主要区别。与Graphics相比,Graphics2D提供的几何图形控制、坐标转换、颜色管理和文本布局的功能更加强大,使用起来更加灵活。
java.swing.Timer类:在指定的时间间隔触发一个或多个ActionEvent。
构造Timer时要指定一个延迟参数和一个ActionListener,延迟参数用于设置初始延迟和事件触发之间的延迟(以毫秒为单位)。启动了计时器后,它将在向已注册侦听器触发第一个ActionEvent之前等待初始延迟,第一个事件之后,每次超过事件间延迟时它都继续触发事件,直至被停止。
构造之后,可单独更改初始延迟和事件间延迟,并且可以添加其他ActionListener。
如果希望计时器只在第一次时触发然后停止,可以对计时器调用setRepeats(false)。