📄 clockpanel.java
字号:
package client.ds;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.*;
/**
* 绘制时钟面板
*
* @author elegate
* @since 2007-10-22
* @version 0.1
*/
public class ClockPanel extends JPanel implements ClockI {
/**
*
*/
private static final long serialVersionUID = -8540617832921070650L;
/**
* 背景色
*/
public static final Color BACKGROUND_COLOR = Color.PINK;
/**
* 表盘颜色
*/
public static final Color DIAL_COLOR = Color.BLACK;
/**
* 指针颜色
*/
public static final Color HAND_COLOR = Color.DARK_GRAY;
/**
* 时间
*/
private Calendar c = null;
/**
* 中心坐标
*/
private int x, y;
/**
* 表盘半径
*/
private int radius;
/**
* 面板高度
*/
private int height;
/**
* 面板宽度
*/
private int width;
private SimpleDateFormat dateFormat;
public ClockPanel() {
dateFormat = new SimpleDateFormat("hh:mm:ss");
}
/**
* 重写绘制函数
*/
public void paintComponent(Graphics g) {
// 如果时间未设置,则不绘制
if (c == null)
return;
Graphics2D g2D = (Graphics2D) g;
// 消除锯齿
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// 绘制背景
Rectangle r = g2D.getClipBounds();
g2D.setColor(BACKGROUND_COLOR);
g2D.fill(r);
// 计算相关参数
height = r.height;
width = r.width;
radius = (int) (Math.min(r.height, r.width) * 0.6) / 2;
x = (width - 2 * radius) / 2 + radius;
y = (height - 2 * radius) / 2 + radius;
// 绘制表盘
drawDial(g2D);
// 绘制指针
drawHands(g2D);
// 绘制数字时钟
Font f = g2D.getFont();
f = f.deriveFont(30.0f);
f = f.deriveFont(Font.BOLD);
g2D.setFont(f);
FontRenderContext frc = g2D.getFontRenderContext();
String time = dateFormat.format(c.getTime());
Rectangle2D bound = f.getStringBounds(time, frc);
double startX = x - bound.getWidth() / 2;
double startY = ((height - 2 * radius) / 2 - bound.getHeight()) / 2
+ bound.getHeight();
g2D.drawString(time, (float) startX, (float) startY);
}
/**
* @param g
* 绘图环境
*/
public void drawDial(Graphics2D g) {
// 绘制外层表盘
Stroke s = new BasicStroke(8.0f);
g.setStroke(s);
g.setColor(DIAL_COLOR);
double outRadius = radius * 1.05;
Ellipse2D.Double ellipse = new Ellipse2D.Double(x - outRadius, y
- outRadius, 2 * outRadius, 2 * outRadius);
g.draw(ellipse);
// 绘制表盘中心
s = new BasicStroke(3.0f);
g.setStroke(s);
g.setColor(HAND_COLOR);
Ellipse2D.Double dot = new Ellipse2D.Double(x - 5, y - 5, 10, 10);
g.draw(dot);
// 绘制表盘分割线
g.setColor(DIAL_COLOR);
// 绘制长分隔线
s = new BasicStroke(3.0f);
g.setStroke(s);
int r1 = radius, r2 = (int) (radius - radius * 0.1);
drawDelimiter(0, 360, 30, r1, r2, g);
// 绘制短分隔线
s = new BasicStroke(1.0f);
g.setStroke(s);
r2 = (int) (radius - radius * 0.05);
drawDelimiter(0, 360, 6, r1, r2, g);
}
/**
* 绘制分割线
*
* @param start
* 起始绘制位置
* @param end
* 终止绘制位置
* @param step
* 步长
* @param r1
* 半径1
* @param r2
* 半径2
* @param g
* 绘图环境
*/
private void drawDelimiter(int start, int end, int step, double r1,
double r2, Graphics2D g) {
for (int theta = start; theta < end; theta += step) {
double a = theta / 180.0 * Math.PI;
// System.out.println("sin:"+Math.sin(a)+",cos:"+Math.cos(a));
double x1 = x + Math.cos(a) * r1;
double y1 = y - Math.sin(a) * r1;
double x2 = x + Math.cos(a) * r2;
double y2 = y - Math.sin(a) * r2;
Line2D.Double line = new Line2D.Double(x1, y1, x2, y2);
g.draw(line);
}
}
/**
* 绘制指针,通过调用<code>drawHand(double, double, double, Graphics2D)</code>完成三种指针的绘制
*
* @param g
* 绘图环境
* @see #drawHand(double, double, double, Graphics2D)
*/
public void drawHands(Graphics2D g) {
int hour = c.get(Calendar.HOUR);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
double h = hour % 12 + minute / 60.0 + second / 60.0 / 60.0;
double theta = 360 - h / 12 * 360 + 90;
theta = theta * Math.PI / 180;
g.setColor(HAND_COLOR);
// 时针
Stroke s = new BasicStroke(3.0f);
g.setStroke(s);
drawHand(theta, 0.6, 0.08, g);
// 分针
theta = 360 - minute / 60.0 * 360 + 90;
theta *= Math.PI / 180;
s = new BasicStroke(2.0f);
g.setStroke(s);
drawHand(theta, 0.8, 0.05, g);
// 秒针
theta = 360 - second / 60.0 * 360 + 90;
theta *= Math.PI / 180;
s = new BasicStroke(1.0f);
g.setStroke(s);
drawHand(theta, 1.0, 0.03, g);
}
/**
* 绘制单个指针,如分针,时针等,由<code>drawHands(Graphics2D g)</code>调用
*
* @param theta
* 角度,弧度制
* @param factor
* 控制指针长度
* @param deltaTheta
* 控制箭头和指针的夹角
* @param g
* 绘图参数
* @see #drawHands(Graphics2D)
*/
private void drawHand(double theta, double factor, double deltaTheta,
Graphics2D g) {
int r2 = (int) (radius * factor);
// 计算指针头部位置
double x1 = x + Math.cos(theta) * r2;
double y1 = y - Math.sin(theta) * r2;
// 计算指针的箭头位置
// 右侧
double x2 = x + Math.cos(theta - deltaTheta) * r2 * 0.9;
double y2 = y - Math.sin(theta - deltaTheta) * r2 * 0.9;
// 左侧
double x3 = x + Math.cos(theta + deltaTheta) * r2 * 0.9;
double y3 = y - Math.sin(theta + deltaTheta) * r2 * 0.9;
Line2D.Double line = new Line2D.Double(x1, y1, x, y);
g.draw(line);
line = new Line2D.Double(x2, y2, x1, y1);
g.draw(line);
line = new Line2D.Double(x3, y3, x1, y1);
g.draw(line);
line = new Line2D.Double(x2, y2, x3, y3);
g.draw(line);
}
/**
*
*/
public void update(Calendar c) {
this.c = c;
repaint();
}
/**
*
*/
public void update(int hour, int minute, int second) {
if (c == null)
c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, second);
repaint();
}
/**
*
*/
public void update(long time) {
if (c == null)
c = Calendar.getInstance();
c.setTimeInMillis(time);
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 500);
final ClockPanel p = new ClockPanel();
new Thread() {
public void run() {
while (true) {
Calendar c = Calendar.getInstance();
p.update(c);
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
frame.getContentPane().add(p, BorderLayout.CENTER);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -