Swing时钟动画绘制

简介: 本文利用Java原生Swing技术绘制一个时钟动画。

核心结构是JFrame套一个JPanel。

效果:

image.png

Panel代码:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.swing.JLabel;
import javax.swing.JPanel;

public class ClockPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    private int hour, minute, second;

    private int secondX, secondY, minuteX, minuteY, hourX, hourY;

    private Calendar calendar;

    private final SimpleDateFormat sdf;

    private final JLabel timeLabel;

    public ClockPanel() {
        this.setBackground(Color.LIGHT_GRAY);
        this.sdf = new SimpleDateFormat("HH:mm:ss");
        this.timeLabel = new JLabel();
        this.timeLabel.setFont(new Font("黑体", Font.BOLD, 30));
        this.timeLabel.setBounds(250, 50, 100, 40);
        this.add(this.timeLabel);
        this.run();
    }

    public void paint(Graphics g) {
        super.paint(g);
        // 修改时间显示
        this.timeLabel.setText(this.sdf.format(calendar.getTime()));
        Graphics2D graphics2D = (Graphics2D) g;
        // 定义线条宽度为5
        graphics2D.setStroke(new BasicStroke(5));
        // 绿色线条绘制钟表刻度
        g.setColor(Color.pink);
        for (int i = 0; i < 60; i++) {
            int r = 160;
            if (i % 5 == 0) {
                if (i % 15 == 0) {
                    r = 120;
                } else {
                    r = 140;
                }
            }
            int x1 = (int) (300 + sin(i) * r);
            int y1 = (int) (300 - cos(i) * r);
            int x2 = (int) (300 + sin(i) * 180);
            int y2 = (int) (300 - cos(i) * 180);
            g.drawLine(x1, y1, x2, y2);
        }
        // 橙色线条绘制外环
        g.setColor(Color.orange);
        g.drawOval(120, 120, 360, 360);
        // 橙色线条绘制内环
        g.setColor(Color.orange);
        g.drawOval(205, 205, 190, 190);
        // 灰色线条绘制时针
        g.setColor(Color.gray);
        g.drawLine(300, 300, hourX, hourY);
        // 红色线条绘制分针
        g.setColor(Color.red);
        g.drawLine(300, 300, minuteX, minuteY);
        // 黄色线条绘制秒针
        g.setColor(Color.yellow);
        g.drawLine(300, 300, secondX, secondY);
        // 黑色线条绘制轴心
        g.setColor(Color.black);
        g.fillOval(292, 292, 15, 15);
    }

    private double sin(int num) {
        return Math.sin(Math.toRadians(6 * num));
    }

    private double cos(int num) {
        return Math.cos(Math.toRadians(6 * num));
    }

    public void run() {
        new Thread(() -> {
            while (true) {
                calendar = Calendar.getInstance();
                this.second = calendar.get(Calendar.SECOND);
                this.minute = calendar.get(Calendar.MINUTE);
                this.hour = calendar.get(Calendar.HOUR);
                this.secondX = (int) (300 + sin(second) * 150);
                this.secondY = (int) (300 - cos(second) * 150);
                this.minuteX = (int) (300 + sin(minute) * 120);
                this.minuteY = (int) (300 - cos(minute) * 120);
                this.hourX = (int) (300 + Math.sin(Math.toRadians(hour * 30 + minute * 0.5)) * 90);
                this.hourY = (int) (300 - Math.cos(Math.toRadians(hour * 30 + minute * 0.5)) * 90);
                this.repaint();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

}

Frame代码:

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Objects;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class ClockFrame extends JFrame {

    private static final long serialVersionUID = 1L;

    public ClockFrame() {
        this.setTitle("Java时钟");
        this.setBounds(100, 200, 600, 700);
        ClockPanel clockPanel = new ClockPanel();
        this.add(clockPanel);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        ImageIcon imageIcon = new ImageIcon(Objects.requireNonNull(this.getClass().getResource("../../../clock.png")));
        this.setIconImage(imageIcon.getImage());
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                int option = JOptionPane.showConfirmDialog(ClockFrame.this, "确定退出时钟?", "退出", JOptionPane.YES_NO_OPTION);
                if (option == JOptionPane.YES_OPTION && e.getWindow() == ClockFrame.this) {
                    ClockFrame.this.dispose();
                    System.exit(0);
                }
            }
        });
        this.setVisible(true);
    }

}
相关文章
|
2月前
|
图形学
【unity小技巧】最简单的FPS游戏准心跳动动画控制
【unity小技巧】最简单的FPS游戏准心跳动动画控制
13 0
|
2月前
|
Python
Pygame基础3-动画
Pygame基础3-动画
|
3月前
|
移动开发 前端开发 HTML5
使用canvas绘制超炫时钟
使用canvas绘制超炫时钟
21 3
使用canvas绘制超炫时钟
An动画基础之元件的图形动画与按钮动画
An动画基础之元件的图形动画与按钮动画
284 0
An动画基础之元件的图形动画与按钮动画
|
前端开发
canvas炫酷转盘时钟
canvas炫酷转盘时钟,拿来即用
62 0
canvas炫酷转盘时钟
|
移动开发 前端开发 Shell
使用canvas绘制时钟
使用canvas绘制时钟
74 0
|
前端开发
用canvas绘制一个烟花动画
前言 在我们日常开发中贝塞尔曲线无处不在: svg 中的曲线(支持 2阶、 3阶) canvas 中绘制贝塞尔曲线 几乎所有前端2D或3D图形图表库(echarts,d3,three.js)都会使用到贝塞尔曲线 所以掌握贝塞尔曲线势在必得。这篇文章主要是实战篇,不会介绍和贝塞尔相关的知识, 如果有同学对贝塞尔曲线不是很清楚的话:可以查看我这篇文章——深入理解SVG 绘制贝塞尔曲线 第一步我们先创建ctx, 用ctx 画一个二阶贝塞尔曲线看下。二阶贝塞尔曲线有1个控制点,一个起点,一个终点。 const canvas = document.getElementById( 'canvas'
用canvas绘制一个烟花动画
swing 跑马灯特效(不断动态前进的效果)
swing 跑马灯特效(不断动态前进的效果)
312 0
|
存储 图形学
动画系统中的基础动画
动画系统中的基础动画
156 0
动画系统中的基础动画
|
前端开发 图形学 Python
动画系统之2D动画
动画系统之2D动画
162 0
动画系统之2D动画