| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
b4c2
10年前发布

一个精美的java时钟 (自动换背景 秒针平滑移动)

import java.awt.BasicStroke;  import java.awt.Color;  import java.awt.Container;  import java.awt.Font;  import java.awt.Graphics;  import java.awt.Graphics2D;  import java.awt.Image;  import java.awt.MediaTracker;  import java.awt.Toolkit;  import java.awt.geom.Ellipse2D;  import java.awt.geom.Line2D;  import java.awt.image.BufferedImage;  import java.net.URL;  import java.text.DateFormat;  import java.util.Calendar;  import java.util.Date;  import java.util.GregorianCalendar;    import javax.swing.JFrame;  import javax.swing.JLabel;    /**   * 一个精美的时钟 (自动换背景 秒针平滑移动)   *    * 注意:背景图片需放在该包的image目录下(命名:1.jpg...5.jpg)   */  public class Clock extends JFrame {   // 今天的日期对象   private GregorianCalendar now = new GregorianCalendar();   // 时钟标签,上面画的是圆形时钟   private ClockLabel clockLabel = new ClockLabel();   // 星期标签,指示星期   private JLabel weekLabel = new JLabel();   // 日期标签,指示日期   private JLabel dateLabel = new JLabel();   // 品牌标签   private JLabel remarkLabel = new JLabel();   // 时间标签,指示时间   private JLabel timeLabel = new JLabel();     public Clock() {      setTitle("时钟");    setSize(500, 480);    setLocation(((int) Toolkit.getDefaultToolkit().getScreenSize()      .getWidth() - 500) / 2, ((int) Toolkit.getDefaultToolkit()      .getScreenSize().getHeight() - 480) / 2);    init();    setResizable(false);   }     private void init() {      // 初始化品牌标签    remarkLabel.setText("MyClock");    remarkLabel.setLocation(205, 80);    remarkLabel.setSize(100, 30);    remarkLabel.setFont(new Font("Bookman Old Style", Font.BOLD, 20));    remarkLabel.setForeground(Color.orange);      // 初始化星期标签    weekLabel.setSize(60, 20);    weekLabel.setLocation(315, 190);    weekLabel.setForeground(Color.pink);    weekLabel.setFont(new Font("Arial Narrow", Font.BOLD, 12));    // 为星期标签赋值    int week = now.get(Calendar.DAY_OF_WEEK);    switch (week) {    case 1:     weekLabel.setText("SUNDAY");     break;    case 2:     weekLabel.setText("MONDAY");     break;    case 3:     weekLabel.setText("TUESDAY");     break;    case 4:     weekLabel.setText("WEDNESDAY");     break;    case 5:     weekLabel.setText("THURSDAY");     break;    case 6:     weekLabel.setText("FRIDAY");     break;    case 7:     weekLabel.setText("SATURDAY");     break;    }      // 初始化日期标签    dateLabel.setSize(20, 20);    dateLabel.setLocation(375, 190);    dateLabel.setForeground(Color.pink);    dateLabel.setFont(new Font("Fixedsys", Font.BOLD, 12));    dateLabel.setText("" + now.get(Calendar.DATE));      // 初始化时间标签    timeLabel.setSize(500, 30);    timeLabel.setLocation(100, 400);    timeLabel.setForeground(new Color(0, 64, 128));    timeLabel.setFont(new Font("Fixedsys", Font.PLAIN, 15));      // 将各组件加入到主窗口中    Container con = getContentPane();    con.setBackground(Color.white);    con.setLayout(null);    con.add(weekLabel);    con.add(dateLabel);    con.add(remarkLabel);    con.add(timeLabel);    con.add(clockLabel);   }     public static void main(String[] args) {    Clock clock = new Clock();    clock.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    clock.setVisible(true);   }     // 自定义时钟标签,画一个圆形的时钟   class ClockLabel extends JLabel implements Runnable {    // 时钟标签的宽度和高度    private final int WIDTH = 500;    private final int HEIGHT = 440;      // 圆形时钟的X半径和Y半径    private final int CIRCLE_X_RADIUS = 150;    private final int CIRCLE_Y_RADIUS = 155;      // 圆形时钟的原点    private final int CIRCLE_X = 250;    private final int CIRCLE_Y = 200;      // 圆形时钟指针的长度    private final int HOUR_LENGTH = 70;    private final int MIN_LENGTH = 100;    private final int SEC_LENGTH = 135;      // 当前时针所处的角度    double arcHour = 0;    // 当前分针所处的角度    double arcMin = 0;    // 当前秒针所处的角度    double arcSec = 0;      // 颜色的透明度,    int alpha = 60;    // 标识颜色透明度变化的方向,为true时表示越来越透明,为false时表示月来越不透明    boolean flag = false;    // 背景图片的id,轮换显示背景图片时使用    int imageID = 0;    // 背景图片对象数组    Image img[] = new Image[5];    // 背景图片URL,在该包的image目录下(命名:1.jpg...5.jpg)    URL url[] = new URL[] { ClockLabel.class.getResource("image/1.jpg"),      ClockLabel.class.getResource("image/2.jpg"),      ClockLabel.class.getResource("image/3.jpg"),      ClockLabel.class.getResource("image/4.jpg"),      ClockLabel.class.getResource("image/5.jpg"),      ClockLabel.class.getResource("image/6.jpg") };      // 一个具有缓冲区的图像对象    BufferedImage bufferedImage = null;    int imageSize = 2 * Math.max(CIRCLE_X_RADIUS, CIRCLE_Y_RADIUS);    // 为bufferedImage创建的Graphics对象,用于在bufferedImage上画图    Graphics bufferedImageGraphics = null;    // 时钟线程    Thread clockThread = null;    // 计数器    int count = 0;      public ClockLabel() {       // 设置时钟标签的大小     this.setSize(WIDTH, HEIGHT);       // 获取时针、分针、秒针当前的角度     arcHour = now.get(Calendar.HOUR) * (360.0 / 12)       + now.get(Calendar.MINUTE) * (360.0 / 12 / 60)       + now.get(Calendar.SECOND) * (360.0 / 12 / 60 / 60);     arcMin = now.get(Calendar.MINUTE) * (360.0 / 60)       + now.get(Calendar.SECOND) * (360.0 / 60 / 60);     arcSec = now.get(Calendar.SECOND) * (360.0 / 60);       // 根据图片URL创建图片对象     Toolkit tk = this.getToolkit();     img[0] = tk.createImage(url[0]);     img[1] = tk.createImage(url[1]);     img[2] = tk.createImage(url[2]);     img[3] = tk.createImage(url[3]);     img[4] = tk.createImage(url[4]);     try {      // 使用MediaTracker加载图片对象      // MediaTracker 类是一个跟踪多种媒体对象状态的实用工具类,      // 媒体对象可以包括音频剪辑和图像,但目前仅支持图像.      MediaTracker mt = new MediaTracker(this);      mt.addImage(img[0], 0);      mt.addImage(img[1], 0);      mt.addImage(img[2], 0);      mt.addImage(img[3], 0);      mt.addImage(img[4], 0);      // 加载媒体跟踪器中所有的图像。      mt.waitForAll();     } catch (Exception e) {      e.printStackTrace();     }       // 创建一个有缓冲的Image对象     bufferedImage = new BufferedImage(imageSize, imageSize,       BufferedImage.TYPE_INT_ARGB);     // 为BufferedImage创建Graphics2D对象,     // 以后用该Graphics2D对象画的图都会画在BufferedImage中     bufferedImageGraphics = bufferedImage.createGraphics();       // 启动线程     clockThread = new Thread(this);     clockThread.start();    }      public void paint(Graphics g1) {     // Graphics2D继承Graphics,比Graphics提供更丰富的方法     Graphics2D g = (Graphics2D) g1;       /** ***画圆形时钟的刻度,每6度便有一个刻度**** */     for (int i = 0; i < 360; i = i + 6) {      g.setColor(Color.gray);      // 设置画笔的宽度为2      g.setStroke(new BasicStroke(2));        // 画刻度      if (i % 90 == 0) {       // 对于0,3,6,9点位置,使用一个大的刻度       g.setColor(Color.pink);       g.setStroke(new BasicStroke(7));// 画笔宽度为5       // 当起点和终点一样时,画的就是点       g.drawLine(         CIRCLE_X           + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS),         CIRCLE_Y           + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS),         CIRCLE_X           + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS),         CIRCLE_Y           + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS));      } else if (i % 30 == 0) {       // 如果角度处于小时的位置,而且还不在0,3,6,9点时,画红色的小刻度       g.setColor(Color.orange);       g.setStroke(new BasicStroke(3));// 画笔宽度为3       g.drawLine(         CIRCLE_X           + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS),         CIRCLE_Y           + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS),         CIRCLE_X           + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS),         CIRCLE_Y           + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS));      } else {       // 其他位置就画小刻度       g.setColor(Color.gray);       g.drawLine(         CIRCLE_X           + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS),         CIRCLE_Y           + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS),         CIRCLE_X           + (int) (Math.cos(i * Math.PI / 180) * CIRCLE_X_RADIUS),         CIRCLE_Y           + (int) (Math.sin(i * Math.PI / 180) * CIRCLE_Y_RADIUS));      }     }       /** ****** 画时钟的指针 ******** */     // 画时针     Line2D.Double lh = new Line2D.Double(CIRCLE_X, CIRCLE_Y, CIRCLE_X       + Math.cos((arcHour - 90) * Math.PI / 180) * HOUR_LENGTH,       CIRCLE_Y + Math.sin((arcHour - 90) * Math.PI / 180)         * HOUR_LENGTH);     // 设置画笔宽度和颜色     g.setStroke(new BasicStroke(8));     g.setColor(Color.pink);     // 利用Graphics2D的draw方法画线     g.draw(lh);       // 画分针     Line2D.Double lm = new Line2D.Double(CIRCLE_X, CIRCLE_Y, CIRCLE_X       + Math.cos((arcMin - 90) * Math.PI / 180) * MIN_LENGTH,       CIRCLE_Y + Math.sin((arcMin - 90) * Math.PI / 180)         * MIN_LENGTH);     g.setStroke(new BasicStroke(4));     g.setColor(Color.orange);     g.draw(lm);       // 画秒针     Line2D.Double ls = new Line2D.Double(CIRCLE_X, CIRCLE_Y, CIRCLE_X       + Math.cos((arcSec - 90) * Math.PI / 180) * SEC_LENGTH,       CIRCLE_Y + Math.sin((arcSec - 90) * Math.PI / 180)         * SEC_LENGTH);     g.setStroke(new BasicStroke(1));       g.setColor(Color.lightGray);     g.draw(ls);       /** **** 画时钟背景,并将其透明处理 ******* */     // 所有使用bufferedImageGraphics画的图像,都画在bufferedImage上,     // drawImage方法的参数含义分别是:背景图片对象、目标位置第一个角的X、Y坐标、目标位置第二个角的X、Y坐标、     // 源位置第一个角的X、Y坐标、源位置第二个角的X、Y坐标、图像对象改变时的通知接受者     bufferedImageGraphics.drawImage(img[imageID], 0, 0, imageSize,       imageSize, 0, 0, imageSize + 10, imageSize + 10, this);     // 将背景图片透明化     for (int j = 0; j < imageSize; j++) {      for (int i = 0; i < imageSize; i++) {       // 获得背景图像中(i, j)坐标的颜色值       int pix = bufferedImage.getRGB(i, j);       Color c = new Color(pix);       int R = c.getRed();       int G = c.getGreen();       int B = c.getBlue();       // 通过Color对象的alpha,使颜色透明。       int newpix = new Color(R, G, B, alpha).getRGB();       // 重新设置背景图像该象素点的颜色       bufferedImage.setRGB(i, j, newpix);      }     }       /** 以上画背景操作都是画在bufferedImage上的,这里要将bufferedImage画在ClockLabel **/     // 将当前用户剪贴区 Clip 与椭圆区域相交,并将 Clip 设置为所得的交集     g.clip(new Ellipse2D.Double(95, 45, imageSize, imageSize));     g.setColor(Color.white);     // 在用户剪贴区画bufferedImage     g.drawImage(bufferedImage, 95, 45, this);    }      public void run() {     try {        while (clockThread != null) {         // 计数       count++;       // 获得完整的日期格式       DateFormat df = DateFormat.getDateTimeInstance(         DateFormat.FULL, DateFormat.FULL);       // 格式化当前时间       String s = df.format(new Date());       timeLabel.setText(s);       // 每动一次对时钟指针的角度进行调整       arcSec += 360.0 / 60 / 10; // 每秒转6度       arcMin += 360.0 / 60 / 60 / 10; // 每60秒转6度       arcHour += 360.0 / 12 / 60 / 60 / 10; // 每3600秒转30度         // 当角度满一圈时,归0       if (arcSec >= 360) {        arcSec = 0;       }       if (arcMin >= 360) {        arcMin = 0;       }       if (arcHour >= 360) {        arcHour = 0;       }       // 实现背景透明度渐变       // 从浅入深,再由深入浅。       if (count % 2 == 0) {// 用于背景替换减速        if (flag) {         alpha += 1;         if (alpha == 60) {          flag = !flag;         }        } else {         alpha -= 1;         if (alpha == 0) {          flag = !flag;          // 当透明度变化一个轮回时,换一张背景图          imageID++;          if (imageID == 4) {           imageID = 0;          }         }        }        if (count >= 2147483647) { // 防溢出         count = 0;        }       }       // 重画时钟标签       repaint();         // 等待0.1秒钟       Thread.sleep(100);        }     } catch (Exception e) {      e.printStackTrace();     }    }   }  }