设计思路:
1、‘开始’监听器的设计
定义一个swing 下的Timer对象,每隔一段时间,触发一次timer的监听器(重新绘制钟表面板),即令钟表可以走动
2、钟表的设计
难点在于钟表角度的绘制,
在这里为钟表加上了一个辐射渐变背景图
详情见代码注释:
3、‘停止’按钮的设计
即timer.stop();
三个类:
1、钟表面板设计类
2、注面板设计类
3、main类
package my3;
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Swing2
{
private static void createGUI()
{
// JFrame指一个窗口,构造方法的参数为窗口标题
// 语法:因为MyFrame是JFrame的子类,所以可以这么写
JFrame frame = new MyFrame("Js钟表");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口的其他参数,如窗口大小
frame.setSize(700, 450);
// 显示窗口
frame.setVisible(true);
}
public static void main(String[] args)
{
// 此段代码间接地调用了 createGUI()
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run()
{
createGUI();
}
});
}
}
package my3;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class MyFrame extends JFrame
{
CustomClock clock=new CustomClock();
Timer timer;
public MyFrame(String title)
{
super(title);
// Content Pane
JPanel root = new JPanel();
this.setContentPane(root);
root.setLayout(new BorderLayout());
root.add(clock, BorderLayout.CENTER);
// 工具栏
Box toolbar = Box.createHorizontalBox();
JButton startButton = new JButton("开始");
JButton stopButton = new JButton("停止");
toolbar.add(startButton);
toolbar.add(Box.createHorizontalStrut(10));
toolbar.add(stopButton);
root.add(toolbar, BorderLayout.PAGE_START);
startButton.addActionListener( (e)->{
startClock();
});
stopButton.addActionListener( (e)->{
stopClock();
});
}
private void startClock()
{
if(timer!=null) return;
//创建定时器,每隔1000毫秒执行一次
//第一个参数是delay
//第二个参数为ActionListener,可以用匿名类或者Lamada表达式
// timer=new Timer(1000,(e)-> {
// clock.repaint(); //重置时钟
// });
//匿名类
timer=new Timer(1000,new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clock.repaint();
}
});
timer.start();
}
private void stopClock()
{
if(timer != null)
{
timer.stop();
timer = null;
}
}
}
package my3;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.Calendar;
import javax.swing.JPanel;
public class CustomClock extends JPanel
{
@Override
protected void paintComponent(Graphics g)
{
int width=this.getWidth();
int height=this.getHeight();
Graphics2D g2d=(Graphics2D)g;
// 平滑绘制 ( 反锯齿 )
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.white);
g2d.fillRect(0, 0, width, height);
// 取得一个最大的正文形
//Rectangle rect = new Rectangle(0,0,200,200);
int w = width;
int h = width;
if( h > height)
{
h = height;
w = height;
}
Rectangle rect = new Rectangle((width-w)/2, (height-h)/2, w, h);
rect.grow(-4,-4); // 往里缩一点
//中心点以及半径
int centerX=(int)rect.getCenterX();
int centerY=(int)rect.getCenterY();
int radius=(int)rect.width/2;
//////////////表盘的圆框 /////////////
if(true)
{
// 背景填充白色
// g2d.setPaint(new Color(0xFFFFFF));
// g2d.fillOval(rect.x, rect.y, rect.width, rect.height);
// 边框
g2d.setStroke(new BasicStroke(4));
g2d.setPaint(Color.RED);
g2d.drawOval(rect.x, rect.y, rect.width, rect.height);
}
/////////////// 刻度 /////////////////
if(true)
{
g2d.setStroke(new BasicStroke(4));
for(double angle=0;angle<360;angle+=30)
{
drawRadialLine(g2d, centerX, centerY, radius, angle);
}
//截断辐条得到刻度
radius-=5;
// g2d.setPaint(Color.WHITE);
// g2d.fillOval(centerX-radius, centerY-radius, radius*2, radius*2);
//中心画一个小圆点
int r=4;
g2d.setPaint(Color.RED);
g2d.fillOval(centerX-r, centerY-r, r*2, r*2);
}
//辐射渐变填充
if(true)
{
Point2D center=new Point2D.Double(centerX,centerY);
float[] dist= {0.0f,0.2f,1.0f}; //距离
Color[] colors = { Color.RED, Color.WHITE, Color.BLUE }; //颜色
//Gradient 梯度
RadialGradientPaint paint=new RadialGradientPaint(center,radius,dist,colors);
g2d.setPaint(paint);
g2d.fillOval(centerX-radius, centerY-radius, radius*2, radius*2);
}
//////////////秒针,分针,时针 ///////////
//得到时分秒值
Calendar cal=Calendar.getInstance();
int hour=cal.get(Calendar.HOUR);
int minute=cal.get(Calendar.MINUTE);
int second=cal.get(Calendar.SECOND);
//时针
if(true)
{
double radius2=radius*0.5;
g2d.setPaint(Color.ORANGE);
g2d.setStroke(new BasicStroke(6));
//计算角度
double vv=hour+minute/60.0;
drawRadialLine(g2d,centerX,centerY,radius2,vv/12.0*360-90);
}
// 分针
if(true)
{
double radius2 = radius *0.7;
g2d.setPaint(Color.GREEN);
g2d.setStroke(new BasicStroke(3));
double vv = minute + second/60.0; // 角度计算有一点点复杂
drawRadialLine(g2d, centerX, centerY, radius2, minute/60.0 * 360 - 90);
}
// 秒针
if(true)
{
double radius2 = radius *0.9;
g2d.setPaint(Color.RED);
g2d.setStroke(new BasicStroke(1));
drawRadialLine(g2d, centerX, centerY, radius2, second/60.0 * 360 - 90 );
}
}
// 绘制从圆心发散出的辐条线条,中心centerX, centerY, 半径radius, 角度angle
private void drawRadialLine(Graphics2D g2d,
double centerX, double centerY,
double radius, double angle)
{
double radian=angle/180*Math.PI; //角度转化为弧度
double x = centerX + radius * Math.cos( radian );
double y = centerY + radius * Math.sin( radian );
Line2D line=new Line2D.Double(x, y, centerX, centerY);
g2d.draw(line);
}
}
来源:https://blog.csdn.net/gjs935219/article/details/99057569