繼承 JFrame,覆寫 paint(Graphics) 繪製類比時鐘面板:外圓、刻度數字(1~12)、時/分/秒三支指針,並以 javax.swing.Timer 每秒觸發 repaint() 更新指針角度,右上角顯示數位時間(HH:mm:ss)。
(200,200),半徑 200px。90 - second * 690 - minute * 690 - hour * 30 - minute / 2Graphics2D 設定 BasicStroke 調整指針粗細(秒針 1.0、分針 2.2、時針 4.3)。import java.awt.*;
import java.awt.event.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.*;
public class AnalogClock extends JFrame implements ActionListener {
private static final double RAD = Math.PI / 180;
public AnalogClock() {
super("Analog Clock");
setSize(400, 400);
setLocation(400, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground(Color.WHITE);
setResizable(true);
setVisible(true);
// 每秒重繪
new Timer(1000, e -> repaint()).start();
addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) { System.exit(0); }
});
}
@Override public void paint(Graphics g) {
super.paint(g); // 清背景
Graphics2D g2 = (Graphics2D) g;
Insets ins = getInsets();
int h = getSize().height;
int cx = 200, cy = 200; // 固定中心(簡化版)
// 表盤外圓
g2.setStroke(new BasicStroke(3f));
g.drawOval(40, 40, h - 80, h - 80);
// 刻度數字 1~5 (右上區)
int R1 = 140, angle = 60;
for (int i = 1; i <= 5; i++, angle -= 30) {
int x = (int) (cx + R1 * Math.cos(RAD * angle));
int y = (int) (cy - R1 * Math.sin(RAD * angle));
g.setFont(new Font("標楷體", Font.BOLD, 20));
g.drawString(String.valueOf(i), x, y);
}
// 刻度數字 7~11 (左下區)
int R2 = 150; angle = -120;
for (int i = 7; i <= 11; i++, angle -= 30) {
int x = (int) (cx + R2 * Math.cos(RAD * angle));
int y = (int) (cy - R2 * Math.sin(RAD * angle));
g.drawString(String.valueOf(i), x, y);
}
g.drawString("6", 190, 350);
g.drawString("12", 190, 60);
// 目前時間
Calendar now = new GregorianCalendar();
int hour = now.get(Calendar.HOUR_OF_DAY);
int min = now.get(Calendar.MINUTE);
int sec = now.get(Calendar.SECOND);
String time = String.format("%02d:%02d:%02d", hour, min, sec);
g.setColor(Color.WHITE);
g.fillRect(10, 30, 90, 28);
g.setColor(Color.RED);
g.drawString(time, 10, 50);
// 指針角度
int S = 90 - sec * 6;
int M = 90 - min * 6;
int H = 90 - hour * 30 - min / 2;
// 秒針(黑,細)
drawHand(g, cx, cy, 130, S, Color.BLACK, 1.0f, true);
// 分針(藍,中)
drawHand(g, cx, cy, 110, M, Color.BLUE, 2.2f, true);
// 時針(綠,粗)
drawHand(g, cx, cy, 90, H, Color.GREEN, 4.3f, false);
}
/** 繪製單支指針,erase=true 先以背景色抹除上一幀 */
private void drawHand(Graphics g, int cx, int cy, int len, int angleDeg,
Color color, float thickness, boolean erase) {
Graphics2D g2 = (Graphics2D) g;
int x = (int) (cx + len * Math.cos(RAD * angleDeg));
int y = (int) (cy - len * Math.sin(RAD * angleDeg));
if (erase) {
int prev = 90 - (angleDeg == 90 - (int)(len==130?0:0) ? 0 : 0); // 簡化:實際需記錄上一角度
// 此處為示意,完整版建議保存上一角度至欄位
}
g2.setStroke(new BasicStroke(thickness));
g.setColor(color);
g.drawLine(cx, cy, x, y);
}
@Override public void actionPerformed(ActionEvent e) {} // Timer 使用 Lambda
public static void main(String[] args) {
SwingUtilities.invokeLater(AnalogClock::new);
}
}
drawHand 才能正確抹除,避免殘影。AffineTransform 旋繪製指針圖形(如三角形箭頭),比單線條更美觀。g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);getWidth()/getHeight() 動態計算中心與半徑。