import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
/**
* 画我的钟表
*
* @author Eiffel
*
*/
public class MyClock extends JFrame {
MyPanel mp = null;
public MyClock() {
// 创建我的面板
mp = new MyPanel();
// 添加线程
Thread t = new Thread(mp);
t.start();
// 设置窗体属性
this.add(mp);
this.setTitle("时钟");
this.setBounds(500, 150, 400, 300);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String args[]) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
// 启动程序
new MyClock();
}
}
class MyPanel extends JPanel implements Runnable {
Calendar currentTime = null;
//控制点的大小
double s = 0.04;
public MyPanel() {
// 获取当前时间
currentTime = Calendar.getInstance();
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
//画时钟
drawClock(g2d);
}
// 设置当前Calendar
public void setCurrentTime(Date time) {
this.currentTime.setTime(time);
}
// 设置当前Calendar
public void setCurrentTime(long millis) {
this.currentTime.setTimeInMillis(millis);
}
// 画出时钟
private void drawClock(Graphics2D g2d) {
// 反锯齿开关开,图像变得平滑
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Insets insets = getInsets();
// 宽
int wid = getWidth() - insets.left - insets.right;
// 高
int hei = getHeight() - insets.top - insets.bottom;
// 定义出最长指针(半径)(去除面板的最小边计算)(画出了最大的时钟)
//int r = (int) ((Math.min(wid, hei)) / 2 / (1 + s));
int r = (int) ((Math.min(wid, hei)) / 2/(1+s));
// 把绘图平移
g2d.translate(insets.left + r * (1 + s), insets.top + r * (1 + s));
// 将当前 Graphics2D Transform 与缩放转换连接
g2d.scale(1, -1);
// 画出60个点
for (int i = 0; i < 60; i++) {
// 角度
int angel = 90 - i * 6;
double pos[] = operatPos(r, angel);
// 画点
paintDot(r, g2d, pos[0], pos[1], i);
}
// 画秒针
paintSecoundPointer(r, g2d);
// 画时针
paintHourPointer(r, g2d);
// 画分针
paintMinutePointer(r, g2d);
// 画中点
paintCenterPoint(g2d);
g2d.translate(-insets.left - r * (1 + s), -insets.top - r * (1 + s));
g2d.scale(1, -1);
}
// 画秒针
private void paintSecoundPointer(double r, Graphics2D g2d) {
g2d.setColor(Color.BLACK);
// 获得秒数
int second = currentTime.get(Calendar.SECOND);
int angle = 90 - second * 6;
double pos[] = operatPos(r * 0.9, angle);
double pos1[] = operatPos(r * 0.2, angle + 180);
Line2D line = new Line2D.Double(pos1[0], pos1[1], pos[0], pos[1]);
g2d.draw(line);
// g2d.drawLine((int)pos1[0], (int)pos1[1], (int)pos[0], (int)pos[1]);
}
// 画时针
private void paintHourPointer(double r, Graphics2D g2d) {
// 获得小时时间
int hour = currentTime.get(Calendar.HOUR);
// 获得分钟时间
int minute = currentTime.get(Calendar.MINUTE);
// 获得秒时间
int second = currentTime.get(Calendar.SECOND);
// 计算角度(1小时是30度)
double angle = 90 - (hour + minute / 60.0 + second / 3600.0) * 30;
// 多边形针(第一个参数确定指针长短,第二个确定指针拐点位置,第三个确定指针尾部的位置)
Shape pointerShape = createPointerShape(r * 0.6, r * 0.06, r * 0.1,
angle);
// double pos[] = operatPos(r, angle);
// 画时针
g2d.setColor(Color.LIGHT_GRAY);
g2d.fill(pointerShape);
// 画时针边框
g2d.setColor(Color.DARK_GRAY);
g2d.draw(pointerShape);
}
// 画分针
private void paintMinutePointer(double r, Graphics2D g2d) {
// 获得分钟时间
int minute = currentTime.get(Calendar.MINUTE);
// 获得秒时间
int secound = currentTime.get(Calendar.SECOND);
// 计算弧度
double angle = 90 - (minute + secound / 60.0) * 6;
Shape pointerShape = createPointerShape(r * 0.8, r * 0.04, r * 0.08,
angle);
g2d.setColor(Color.LIGHT_GRAY);
g2d.fill(pointerShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(pointerShape);
}
/*
* 画指针 创建指针路径多变形
*
* @param r1 从圆心到指针定点的长度
*
* @param r2 从圆心到指针侧边端点的距离
*
* @param r3 从圆心到指针尾部端点的距离
*
* @param angle 指针角度
*
* @return
*/
private Shape createPointerShape(double r1, double r2, double r3,
double angle) {
GeneralPath gp = new GeneralPath();
double[] pos = operatPos(r1, angle);// 指针定点
double[] pos1 = operatPos(r2, angle + 90);// 指针侧边断点
gp.append(new Line2D.Double(pos[0], pos[1], pos1[0], pos1[1]), true);
double[] pos2 = operatPos(r3, angle + 180);// 指针尾部
gp.lineTo((float) pos2[0], (float) pos2[1]);
double[] pos3 = operatPos(r2, angle + 270);// 指针的另一侧边断点(上侧)
gp.lineTo((float) pos3[0], (float) pos3[1]);
gp.closePath();
return gp;
}
/*
* 画时钟中间那一点
*
* @param g2d
*/
private void paintCenterPoint(Graphics2D g2d) {
g2d.setColor(Color.BLUE);
// 前两个参数坐标,后两个参数大小
Rectangle2D rect = new Rectangle2D.Double(-2, -2, 6, 6);
g2d.fill(rect);
}
// 画出60个点
private void paintDot(int r, Graphics2D g, double x, double y, int i) {
int flag = 0;
if (i % 15 == 0) {
g.setColor(Color.RED);
flag = 2;
} else if (i % 5 == 0) {
g.setColor(Color.GREEN);
flag = 2;
} else {
g.setColor(Color.BLACK);
flag = 1;
}
if (flag == 2) {
// 第一个Ellipse2D 的窗体矩形左上角的 X 坐标,第二个Ellipse2D 的窗体矩形左上角的 Y 坐标
// 第三个参数Eclipse2D总高度,第四个参数总宽度,
// 说简单点 前两个表示坐标,后两个表示大小
Ellipse2D rect = new Ellipse2D.Double(x - r * s, y - r * s, r * s
* 2, r * s * 2);
g.fill(rect);
} else if (flag == 1) {
Ellipse2D rect = new Ellipse2D.Double(x - r * 0.02, y - r * 0.02,
r * 0.04, r * 0.04);
g.fill(rect);
}
}
// 计算公式(根据半径和弧长计算坐标)
public double[] operatPos(double r, double angle) {
// 角度转换成弧度
// System.out.println("角度是:" + angle);
double radian = Math.toRadians(angle);
// System.out.println("弧度是:" + angle);
double x = r * Math.cos(radian);
double y = r * Math.sin(radian);
// 范围数组
return new double[] { x, y };
}
// 执行线程
@Override
public void run() {
while (true) {
try {
// 间隔一秒刷新面板
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 重新得到当前的时间,并设置
setCurrentTime(System.currentTimeMillis());
// 重绘
this.repaint();
}
}
}