1 import java.awt.Color; 2 import java.awt.Font; 3 import java.awt.Graphics; 4 import java.util.Calendar; 5 import java.util.GregorianCalendar; 6 7 import javax.swing.JFrame; 8 import javax.swing.JPanel; 9 10 /** 11 * 12 * @author YYCat 13 * 14 */ 15 public class TestImitateClock extends JPanel{ 16 17 private static final long serialVersionUID = 1L; 18 19 public static final int DEFAULT_HEIGHT = 350; //面板的高度 20 public static final int DEFAULT_WIDTH = 300; //面板的宽度 21 public static final int DEFAULT_X = 100; //面板初始位置 22 public static final int DEFAULT_Y = 50; 23 public static final int PADDING_X = 30; 24 public static final int PADDING_Y = 60; 25 public static final int clockRadius = (DEFAULT_WIDTH-60)/2; //定义时钟圆的半径radius 26 int xCenter = PADDING_X + clockRadius; //时钟圆的圆心坐标 27 int yCenter = PADDING_Y + clockRadius; 28 29 /** 30 * 定义时间变量,便于计算对应的时、分、秒针对应的位置 31 */ 32 private int second, minute, hour; 33 34 public TestImitateClock(){ 35 initTime(); 36 } 37 38 39 40 public void paint(Graphics g){ 41 /** 42 * 画时钟轮廓 43 * 定义半径clockRadius:120px; 44 */ 45 46 // int clockRadius = DEFAULT_WIDTH - 60; //半径为 (300-600)/2 47 g.drawOval(PADDING_X, PADDING_Y, clockRadius*2, clockRadius*2); 48 49 paintClockNum(g); 50 51 paintClockHands(g); 52 53 54 } 55 56 /** 57 * 画时钟数字 58 * @param g 59 */ 60 public void paintClockNum(Graphics g){ 61 62 int strLength = xCenter - PADDING_X; 63 Font afterFont = new Font("宋体", Font.BOLD, 14); 64 Font beforeF = g.getFont(); 65 66 for(int i=0; i<12; i++){ 67 if(i%3==0){ //固定位置数字加粗显示 68 g.setFont(afterFont); 69 } 70 g.drawString(i*1 + "", (int) (xCenter + strLength*Math.sin(2*Math.PI/12*i)), (int) (yCenter + strLength*Math.cos(Math.PI + 2*Math.PI/12*i))); 71 g.setFont(beforeF); 72 } 73 74 } 75 76 /** 77 * 画时针、分针、秒针 78 */ 79 public void paintClockHands(Graphics g){ 80 81 /** 82 * 设置时分秒针的长度、颜色、宽度 83 */ 84 double secondLen = clockRadius * 0.85; 85 double minuteLen = clockRadius * 0.75; 86 double hourLen = clockRadius * 0.65; 87 88 Color colorBefore = g.getColor(); 89 90 91 //秒针 92 g.setColor(Color.RED); 93 g.drawLine(xCenter, yCenter, (int)(xCenter + secondLen*Math.sin(2*Math.PI/60*second)),(int)( yCenter + secondLen*Math.cos(Math.PI+2*Math.PI/60*second))); 94 95 //分针 96 g.setColor(Color.CYAN); 97 g.drawLine(xCenter, yCenter, (int)(xCenter + minuteLen*Math.sin(2*Math.PI/60*minute)),(int)( yCenter + minuteLen*Math.cos(Math.PI+2*Math.PI/60*minute))); 98 99 //时针 100 g.setColor(Color.DARK_GRAY); 101 g.drawLine(xCenter, yCenter, (int)(xCenter + hourLen*Math.sin(2*Math.PI/12*hour)),(int)( yCenter + hourLen*Math.cos(Math.PI+2*Math.PI/12*hour))); 102 103 g.setColor(colorBefore); 104 } 105 /** 106 * 获取时间 107 */ 108 public void initTime(){ 109 Calendar calendar = new GregorianCalendar(); 110 second = calendar.get(Calendar.SECOND); 111 minute = calendar.get(Calendar.MINUTE); 112 hour = calendar.get(Calendar.HOUR_OF_DAY); //24小时制 113 114 } 115 public static void main(String[] args){ 116 117 final JFrame frame = new JFrame(); 118 frame.setTitle("Clock"); 119 frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 120 frame.setLocation(DEFAULT_X, DEFAULT_Y); 121 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 122 frame.setVisible(true); 123 124 Thread thread = new Thread(){ 125 public void run(){ 126 while(true){ 127 TestImitateClock clock = new TestImitateClock(); 128 frame.add(clock); 129 clock.setVisible(true); 130 frame.validate(); //接下来会每隔一秒重绘一次时钟——即(从frame中将clock组件删除),因此调用validate方法,使容器重新布置其子组件 131 try { 132 Thread.sleep(1000); 133 } catch (InterruptedException e) { 134 // TODO Auto-generated catch block 135 e.printStackTrace(); 136 } 137 clock.setVisible(false); 138 frame.remove(clock); //在父容器中将其删除 139 clock.invalidate(); //使容器失效 140 } 141 } 142 }; 143 144 thread.start(); 145 } 146 147 }
运行效果如图:
使用到frame.add(panel) //向容器中添加面板组件
frame.validate() //使容器再次布置其子组件,在修改此容器的子组件时使用
Thread thread = new Thread(){...} //线程的使用,这里并没有使用太高深的东西
Math.sin() //函数见API