アナログ時計


アナログ時計を作ってみました。時計の針を描画するには,針の先端のxy座標を計算しなければなりません。これがやっかいです。
参考書籍などで,数学関数のsin,cosや,ラジアン値を参考にして下さい。
アナログ時計のJava Applet

ソースコード

import java.applet.*;
import java.awt.*;
import java.util.*;   		//Dateクラスが属する

public class ja03b extends Applet implements Runnable
{
  int w,h;              	//時計を描画する領域の幅と高さ
  int centerX,centerY;  	//時計の中心座標
  int r;    			//時計の針が動く円形領域の半径
  Date nowtime;   		//現在時刻を格納 
  Thread td;      		//スレッド
  FontMetrics fm; 		//フォントメトリックス
  Font f;

  public void init(){
    w = size().width;   	//Appletのサイズを取得
    h = size().height;
    if(w<h)h = w;       //Appletの幅と高さが異なる場合,時計の描画領域の幅と高さを同じにする
    else w = h;
    centerX = w/2;    		//時計の中心座標を求める。
    centerY = h/2;
    r = (w/2) * 4 / 5; 		//時計の針が動く円形領域の半径を4/5に小さくする。
    nowtime = new Date(); 	//現在時刻を取得
    f = new Font("TimesRoman",Font.BOLD,w/8); //フォントを設定
  }

  public void start(){
    if(td == null){
      td = new Thread(this);
      td.start();
    }
  }

  public void stop(){
    td.stop();
    td = null;
  }

  public void run(){
    while(td != null){
      repaint();
      try{
        Thread.sleep(1000);   		//1秒間隔でスレッドを実行
      }catch(InterruptedException e){}
    }
  }

  public void paint(Graphics g){
    g.setColor(Color.black);
    g.fillRect(0,0,w,h);    		//時計表示領域全体を黒色で塗り潰す
    g.setColor(Color.lightGray);
    g.fillOval(0,0,w,h);    		//薄灰色で塗り潰された円を描く

    g.setColor(Color.blue); 		//時計の数字を描画するための,色,フォント,フォントメトリックス
    g.setFont(f);
    fm =g.getFontMetrics();

    for(int i = 1;i <= 12; i++){  	//1〜12の数字を描画
      String st = "" + i;
      int stw = fm.stringWidth(st); 	//描画する数字の幅
      int sth = fm.getAscent();     	//描画する数字の高さ
      int stx = (int)(centerX +(w/2 -8) * Math.sin(2 * Math.PI * i/12) - stw/2);
      int sty = (int)(centerY -(w/2 -8) * Math.cos(2 * Math.PI * i/12) + sth/2);
        	//(w/2-8)は,数字を描画する円領域の半径(時計全体の円より8ピクセルだけ小さくする)
        	//(2 * Math.PI * i/12)は,数字を描画する位置のラジアン値を計算
        	//-stw/2,+sth/2は,数字の描画位置の調整
      g.drawString(st,stx,sty);
    }
  }

  public void update(Graphics g){
    g.setColor(Color.pink);
    g.fillOval(centerX - r,centerY - r,2*r,2*r);  //時計の針が動く円形領域をピンク色で塗り潰す

    nowtime = new Date(); //現在時刻を取得
    int h = nowtime.getHours();   		//現在時刻から,時間,分,秒を取得
    int m = nowtime.getMinutes();
    int s = nowtime.getSeconds();

    g.setColor(Color.black);
    double hra = 2 * Math.PI * (h + m/60.0) / 12.0;   	//現在時間のラジアン値を計算
    int hx = (int)(centerX + r*0.5 * Math.sin(hra)); 	//時針の先端のx座標(長さを半径rの半分に)
    int hy = (int)(centerY - r*0.5 * Math.cos(hra));	//同じくy座標を計算
    g.drawLine(centerX,centerY,hx,hy);    		//時針を描画

    double mra = 2 * Math.PI * (m + s/60.0) / 60.0;   	//現在の分のラジアン値を計算
    int mx = (int)(centerX + r*0.8 * Math.sin(mra));  	//分針の先端のx座標(長さを半径rの0.8倍に)
    int my = (int)(centerY - r*0.8 * Math.cos(mra)); 	//同じくy座標を計算
    g.drawLine(centerX,centerY,mx,my);    		//分針を描画

    g.setColor(Color.red);
    double sra = 2 * Math.PI * s / 60.0;      		//秒針のラジアン値を計算
    int sx = (int)(centerX + r*0.9 * Math.sin(sra));
    int sy = (int)(centerY - r*0.9 * Math.cos(sra));
    g.drawLine(centerX,centerY,sx,sy);
  }
}

末尾