核心结构是JFrame套一个JPanel。
效果:
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);
}
}