Java2实用教程第5版 14.4

此博客介绍了如何使用Java Swing和Canvas类创建一个实时动态时钟,利用Timer类定时更新显示,包括秒针、分钟针和小时针的动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值