トップページ > Java3D入門 > Java3Dの座標変換(6)
Javaには“Timer”(タイマー)というクラスがあります。 このタイマークラスを使うと、ある処理を一定の時間間隔で繰り返すことができます。 (マイコンでいうタイマー割り込みのようなものです) このタイマーで繰り返す処理を、Java3Dにおける座標変換にしてみます。 一定の時間間隔で座標変換を何度も繰り返すと、物体がどんどん動いていきます。 これでお手軽なアニメーションを作ることができます。 今回は単純に、このTimerの使い方だけを確認します。
タイマーを使うためには、2つのクラスのインスタンスを生成する必要があります。 1つは“Timer”クラスのインスタンスで、もう1つは“TimerTask”クラスを継承したクラスです。 (TimerTaskクラスそのものではない) Timerクラスはタイマー動作そのものを管理する入れ物のようなものです。 その中へ、実際の処理内容を記述したTimerTaskクラスを入れるイメージです。 TimerTaskクラスの中には、実際に行いたい動作を記述する“run()”メソッドがあります。
今回のテストプログラムでは、1秒おきに「1秒経ちました。」とプロンプト上に表示するだけです。 Timerクラスの使い方のイメージは上図ですが、実際にソースコードを眺めた方が 手順が分かりやすいとおもいます。。。
//****************************************************************************** //Java Timer_test //タイマークラスの使い方 //****************************************************************************** //============================================================================== //インポート・ファイル import java.awt.*; import javax.swing.*; import java.util.*; import java.util.Timer; //============================================================================== //メイン・クラス public class Timer_test { //============================================================================= //メイン・メソッド public static void main(String[] args) { //コンストラクタを呼ぶだけです。 Timer_test test = new Timer_test(); } //============================================================================= //コンストラクタ public Timer_test() { //============================================================================ //まずは、基礎フレームの設定。(今回はただウィンドウを表示するだけ) //============================================================================ JFrame frame = new JFrame(); frame.setSize(250,250); frame.setTitle("Timer_test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); //============================================================================ //タイマーの設定 //============================================================================ //タイマークラスのインスタンスを作成 Timer timer = new Timer(); //タイマーの処理内容として、Messageクラスを設定。呼び出し間隔は1秒に設定。 timer.schedule(new Message(),0,1000); } //============================================================================= //メインクラスの内部クラスとして、タイマー処理のクラスを定義 //============================================================================= class Message extends TimerTask { //タイマー割り込みによる処理内容を記述 public void run() { //今回はメッセージ表示だけです。 System.out.println("1秒経ちました。"); } } } //ソースコードここまで。 //******************************************************************************
何もない、ただのウィンドウが表示されます。 今回のテストプログラムでは、ウィンドウの意味はほとんどありません。 プログラムを終了したい時に、ウィンドウの×ボタンを使いたかっただけです。
メインはこちらのプロンプト画面です。1秒ごとにメッセージが表示されていく様子を確認してください。 もしウィンドウを表示させないと、プログラムを終了するためにコマンドプロンプトそのものを 閉じる必要があります。これだといちいち面倒なので、ただのウィンドウだけを表示させています。 よって、ソースコード中のフレーム(ウィンドウ)生成に関わる部分はタイマーの処理とは全く関係ありません。
これ以降、ソースコードの解説です。
上の2つのクラス・ライブラリには、それぞれ“TimerTask”クラスと“Timer”クラスが入っています。 これをインポートしないとタイマー関係の機能を使うことができません。
//タイマークラスのインスタンスを作成 Timer timer = new Timer(); //タイマーの処理内容として、Messageクラスを設定。呼び出し間隔は1秒に設定。 timer.schedule(new Message(),0,1000);
まず、普通にTimerクラスのインスタンスを生成しています。名前は“timer”としました。 このtimerに対して、“schedule()”メソッドを使って処理内容の設定を行っています。 Messageクラスについては後述です。schedule()メソッドの定義を見ておきます。
schedule(TimerTask task , long delay , long period)…となっています。schedule()メソッドには複数あり、オーバーロードして使うことができますが、 今回はアニメーションに最も多く使われるこのメソッドを選びました。 第一引数の“TimerTask task”というところに、自分で定義したクラスを丸ごといれます。 ここに行いたい処理が入っています。第二引数の“long delay”には、タイマーが始動するまでの遅れを入れます。 今回はすぐに動作開始させたいので“0”としています。第三引数の“long period”には、処理内容を繰り返す 時間間隔を入れます。単位はミリ秒です。今回は1秒ごとに表示を行いたいので、“1000”としました。 (1000[ミリ秒] = 1[秒])
class Message extends TimerTask { //タイマー割り込みによる処理内容を記述 public void run() { //今回はメッセージ表示だけです。 System.out.println("1秒経ちました。"); } }
タイマーで行われる処理内容を記述するクラスです。このクラスは自作のクラスなので、 名前は何でも好きに設定できます。今回は“Message”としました。メッセージを表示する処理だから…ということです。 このクラス内で、run()というメソッドを定義します。既に継承元の“TimerTask”クラスには空のrun()メソッドが実装されているので、 これはオーバー・ライドをやっていることになります。今回はSystem.out.println()でプロンプトに文字列を出しているだけです。
なぜ内部クラスにするのかということですが、少なくとも今回のテストプログラムなら独立したクラスとして定義することができます。 しかし、実際にJava3Dにおいて図形の座標変換をrun()メソッドで行いたい場合は、 run()メソッドから座標変換対象のオブジェクトへアクセスする必要があります。 すると、クラスを別々にした場合だとクラス間をまたがって操作をすることになるので、若干面倒です。 以後、オブジェクトへの操作を簡単にするために、タイマーのクラスはメインクラスの内部クラスとして定義することにします。 (クラスの数が多くなって構成が複雑な場合は、適宜変更することになります。後述。)