−トップへ−

経過時間を正確に計測する

 あるイベントが発生してから,次のイベントが起きる時間を測定する方法を考えてみたいと思います。
 
 すぐに思いつくのはtimerコンポーネントを使う方法です。しかしtimer1.intervalが1000のとき,1秒といわれていますが,これはあまり信頼性がありません。そのため,時間を正確に測定する場合には不向きです。
 
 そのため,時間を正確に測定する場合には,イベントの発生した時刻と,次のイベント発生時の時刻の2つを記録し,その間の時間を求める方法を使います。
 
 下の例では,フォームにボタンを2個,ラベルを1個貼り付けます。そして,下のようにプログラムソースを記述します。

 private
 { Private 宣言 }
  t1,t2:tdatetime; //t1とt2を時間型の変数に宣言する
 public
 { Public 宣言 }
  :
  :
 procedure TForm1.Button1Click(Sender: TObject);
 begin
  t1:=time; //t1に現在の時刻を代入する
 end;
 
 procedure TForm1.Button2Click(Sender: TObject);
  var
   hour,min,sec,msec:word; //4つの変数をword型の整数に宣言する
 begin
  t2:=time-t1; //t2に現在の時刻からt1の時刻を引いた時間を代入する
  decodetime(t2,hour,min,sec,msec); //t2を時間と分と秒とミリ秒に分解する
  label1.Caption:=inttostr(sec)+'秒'+inttostr(msec); //label1に秒とミリ秒を表示する
 end;

 上の例では,button1を押し,次にbutton2を押すと,その間の時間をlabel1に表示します。(ここで表示するのは秒と,ミリ秒だけです。)


 これを使って,ストップウォッチを作ってみます。最初の例では途中の時間を表示しませんでしたが,今度はtimerコンポーネントを使って途中の時間も表示するようにしてみます。

フォームに設置するのは,buttonを1個,labelを7個(見栄えをよくするためです),そしてtimerコンポーネントを貼り付け,下図のようにしてみます。
 
 上の例で,「00」と表示されているラベルは左から,label1,label3,label5,label7です。

 それぞれのコンポーネントの設定は,
 ・ button1.Captionをスタートにします。
 ・ timer1についてはenableをfalse,Intervalあまり小さい数にすると表示が間に合わないような感じがしますので,70くらいにしておきます。

 private
 { Private 宣言 }
  t1,t2:tdatetime; //t1とt2を時間型の変数に宣言する
 public
 { Public 宣言 }
 end;
  :
  :
 procedure TForm1.Button1Click(Sender: TObject);
 var
  hour,min,sec,msec:word; //4つの変数をword型の整数に宣言する
 begin
  if button1.Caption='スタート' then begin //もしbutton1の表示が「スタート」なら
   t1:=time; //t1に現在の時刻を記録
   button1.Caption:='ストップ'; //button1の表示を「ストップ」にする
   timer1.Enabled:=true; //timerを作動させる
  end else begin //button1の表示が「スタート」以外のとき
   timer1.Enabled:=false; //timerを止める
   t2:=time-t1; //現在の時刻からスタート時の時刻を引く
   decodetime(t2,hour,min,sec,msec); //時間を分解
   if hour<10 then begin //もし時間が1ケタなら
    label1.Caption:='0'+inttostr(hour); //label1に0をつけて時間を表示
   end else begin //それ以外のとき
    label1.Caption:=inttostr(hour); //label1に時間をそのまま表示
   end;
   if min<10 then begin //もし分が1ケタなら
    label3.Caption:='0'+inttostr(min); //label3に0をつけて分を表示
   end else begin //それ以外のとき
    label3.Caption:=inttostr(min); //label3に分をそのまま表示
   end;
   if sec<10 then begin //もし秒が1ケタなら
    label5.Caption:='0'+inttostr(sec); //label5に0をつけて秒を表示
   end else begin //それ以外のとき
    label5.Caption:=inttostr(sec); //label5に秒をそのまま表示
   end;
   if msec<100 then begin //もしミリ秒が2ケタ以下なら
    label7.Caption:='0'+inttostr(msec div 10); //label7に0をつけてミリ秒を1/100秒まで表示
   end else begin //それ以外のとき
    label7.Caption:=inttostr(msec div 10); //label7にミリ秒を1/100秒まで表示
   end;
   button1.Caption:='スタート'; //button1の表示を「スタート」にする
  end;
 end;

 procedure TForm1.Timer1Timer(Sender: TObject);
 var
  hour,min,sec,msec:word; //4つの変数をword型の整数に宣言する
 begin
  t2:=time-t1; //現在の時刻からスタート時の時刻を引く
  decodetime(t2,hour,min,sec,msec); //時間を分解
  if hour<10 then begin //もし時間が1ケタなら
   label1.Caption:='0'+inttostr(hour); //label1に0をつけて時間を表示
  end else begin //それ以外のとき
   label1.Caption:=inttostr(hour); //label1に時間をそのまま表示
  end;
  if min<10 then begin //もし分が1ケタなら
   label3.Caption:='0'+inttostr(min); //label3に0をつけて分を表示
  end else begin //それ以外のとき
   label3.Caption:=inttostr(min); //label3に分をそのまま表示
  end;
  if sec<10 then begin //もし秒が1ケタなら
   label5.Caption:='0'+inttostr(sec); //label5に0をつけて秒を表示
  end else begin //それ以外のとき
   label5.Caption:=inttostr(sec); //label5に秒をそのまま表示
  end;
  if msec<100 then begin //もしミリ秒が2ケタ以下なら
   label7.Caption:='0'+inttostr(msec div 10); //label7に0をつけてミリ秒を1/100秒まで表示
  end else begin //それ以外のとき
   label7.Caption:=inttostr(msec div 10); //label7にミリ秒を1/100秒まで表示
  end;
 end;

 これを実行し,「スタート」ボタンを押すと数字が動き始めます。
 
 サンプルプログラムではラップタイムも残せるようにしてみました。興味のある方はご覧ください。

−トップへ−