import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class BallApplet extends Applet
implements Runnable,ActionListener,AdjustmentListener,ItemListener
//Appletクラスを継承して、時間的な処理、ボタンのイベント、スクロールバーのイベントを処理するインターフェイスを実装する。
{
Thread th;
//Threadクラスの変数thを設定
BallCanvas bc;
//BallCanvasクラスの変数bcを設定
//コンポーネント
Button button,button1;
Scrollbar scrbar,scrbar1;
Label angleLabel,speedLabel;
Checkbox ch;
//プロパティ、メンバ
double t=0;
int dt=100;
//時間の刻み幅
int count=0;
double theta=Math.PI/4;
//初期角度
double V=60.0;
//初期速度
final int thetaMax_min=5; //最小角度
final int thetaMax_max=90; //最大角度
final int deltaTheta=5; //角度の刻み幅
final int speedmax_min=30; //最小角度
final int speedmax_max=100; //最大角度
final int deltaspeed=1; //速度の刻み幅
boolean threadFlg =true;
//スレッドのループに利用するフラグ変数
boolean suspendFlg =
false;
//スレッドの一時停止と再開に利用するフラグ変数
//---------------------------------------------------------初期設定用メソッド--------------------------------------------
//メソッド1
public void init(){
this.bc=new BallCanvas(0,0);
//キャンバスをオブジェクト化 theta=thetaMax
//画面の設定を行っていく
//画面上部のパネルの作成 //コンポーネントをオブジェクト化し、細部を決定していく
int theta_i=30;
int speed_i=60;
this.button=new Button("reset");
this.button1=new Button("start");
this.ch=new Checkbox("stopped");
this.scrbar=new Scrollbar(Scrollbar.HORIZONTAL,
theta_i,
this.deltaTheta,
this.thetaMax_min,
this.thetaMax_max+this.deltaTheta); //
this.angleLabel=new Label(theta_i+"deg",Label.CENTER);
this.scrbar1=new
Scrollbar(Scrollbar.HORIZONTAL,speed_i,this.deltaspeed,this.speedmax_min,this.speedmax_max+this.deltaspeed);
this.speedLabel=new Label(speed_i+"m/s",Label.CENTER);
Panel p=new Panel();
//1番目のパネルのオブジェクト化
p.setLayout(new GridLayout(1,5));
//パネルのレイアウトの設定
p.add(ch);
p.add(button1);
p.add(button);
//パネルにコンポーネントを追加していく
p.add(scrbar);
p.add(angleLabel);
//画面下部のラベルの作成
Panel p2=new Panel(); //2番目のパネルの設定
p2.setLayout(new GridLayout(1,3));
p2.add(new Label("Velocity",Label.CENTER));
p2.add(scrbar1);
p2.add(speedLabel);
//アプレットのレイアウトを設定
this.setLayout(new BorderLayout());
this.add(p,BorderLayout.NORTH); //上部にオブジェクトp
this.add(bc,BorderLayout.CENTER);
//中部にキャンバスのオブジェクト
this.add(p2,BorderLayout.SOUTH);
//下部にp2
//リスナーに登録
this.button.addActionListener(this);
this.button1.addActionListener(this);
this.scrbar.addAdjustmentListener(this);
this.ch.addItemListener(this);
this.scrbar1.addAdjustmentListener(this);
th=new Thread(this); //スレッドをオブジェクト化
}
//-------------------------------------実行が始まると呼び出される処理----------------------//
//メソッド2
public
void actionPerformed(ActionEvent ev){
//Resetボタンを押したとき、初期条件の変更を含む
if(ev.getSource()==this.button){
this.t=0;
this.theta=this.scrbar.getValue()*Math.PI/180.0;
this.V=this.scrbar1.getValue();}
if(ev.getSource()==this.button1){
//Startボタンを押したときスレッドをスタートさせる
if(count==0){th.start();
count++;}}
}
public void run(){
while(threadFlg){
double a=9.8;
double x = this.V*Math.cos(this.theta)*t; //方程式
double y= this.V*Math.sin(this.theta)*t-0.5*a*t*t; //方程式
this.bc.setx(x); //x座標を設定
this.bc.sety(y); //y座標を設定
this.bc.repaint(); //オブジェクトを更新
t=t+dt/1000.0; //時間を更新
try{
Thread.sleep(dt);
//dt秒間、スレッドを停止
synchronized(this){
while(suspendFlg){wait();}
//suspendFlg=Trueのときは、スレッドを一時停止
}
}
catch(InterruptedException e){}
}
}
public void adjustmentValueChanged(AdjustmentEvent ev){ //スクロールバーを動かしたとき
if(ev.getSource()==this.scrbar){
this.angleLabel.setText(this.scrbar.getValue()+"deg"); //表示の更新
}
if(ev.getSource()==this.scrbar1){
this.speedLabel.setText("V="+this.scrbar1.getValue()+"m/s");
}
}
public synchronized void itemStateChanged(ItemEvent ev){ //チェックボックスを押したとき一時停止
Checkbox ch = (Checkbox)ev.getItemSelectable();
if(ch.getState()){
this.suspendFlg=true;
}
else{
this.suspendFlg = false;
notify();}}
public void paint (Graphics g){
Dimension
size = getSize();
//ダブルバッファリングという技術を使い、画面のちらつきを抑える
Image back = createImage(size.width, size.height);
Graphics buffer = back.getGraphics();
buffer.drawLine(10, 10, 100, 50);
buffer.drawOval(10, 10, 100, 50);
g.drawImage(back, 0, 0, this);
}
public void stop(){
}
}