■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2007年08月12日

    楽しいJava講座 - 初心者から達人へのパスポート
                  vol.066

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[このメールマガジンは、画面を最大化して見てください。]


========================================================
◆ 01.ゲームのプログラミング
========================================================


今回は、簡単なゲームのプログラムを作ってみましょう。
ハエを撃墜する(たたき落とす)ゲームです。

今回のゲーム・プログラムは絵が2つだけの極めて単純なアニ
メーションにします。
すなわち、右向きに飛ぶハエと左向きに飛ぶハエの2つの絵だけ
を使います。

また、ハエは右へ左へ上へ下へと非常に敏捷に方向転回しながら
空中を飛び回りますが、この様子は乱数を使って表現します。


では、さっそくEclipseを起動してプログラミングを開始しま
しょう。

まず最初にJStudy1プロジェクトの中にjp.co.flsi.lecture.fly
というパッケージを作ってください。

次に、このパッケージの中に下記のようなFlyPictureというクラス
を作りましょう。FlyPictureは、ハエを描画するためのクラスです。
ハエを描画するといっても極めて単純なハエの絵です。こんな単純
な絵じゃ満足できない、という人は自分で描き直してください。

--------------------------------------------------------
package jp.co.flsi.lecture.fly;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;

public class FlyPicture {
   public void drawFly(Graphics2D g2dImage, int x, int y, boolean leftward) {
      g2dImage.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2dImage.setStroke(new BasicStroke(1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
      GeneralPath path = new GeneralPath();
      if (leftward) {
         path.moveTo(x + 3, y + 7);
         path.lineTo(x + 13, y + 7);
         path.lineTo(x + 15, y);
         path.closePath();
         g2dImage.draw(path);
         path.moveTo(x + 3, y + 7);
         path.lineTo(x + 13, y + 7);
         path.lineTo(x + 18, y + 2);
         path.closePath();
         g2dImage.draw(path);
         g2dImage.fillOval(x + 1, y + 7, 15, 4);
         g2dImage.fillOval(x, y + 7, 5, 6);
         g2dImage.drawLine(x + 6, y + 7, x, y + 15);
         g2dImage.drawLine(x + 6, y + 7, x + 8, y + 15);
         g2dImage.drawLine(x + 8, y + 7, x + 13, y + 15);
      }
      else {
         path.moveTo(x + 15, y + 7);
         path.lineTo(x + 5, y + 7);
         path.lineTo(x + 3, y);
         path.closePath();
         g2dImage.draw(path);
         path.moveTo(x + 15, y + 7);
         path.lineTo(x + 5, y + 7);
         path.lineTo(x, y + 2);
         path.closePath();
         g2dImage.draw(path);
         g2dImage.fillOval(x + 2, y + 7, 15, 4);
         g2dImage.fillOval(x + 13, y + 7, 5, 6);
         g2dImage.drawLine(x + 12, y + 7, x + 18, y + 15);
         g2dImage.drawLine(x + 12, y + 7, x + 10, y + 15);
         g2dImage.drawLine(x + 10, y + 7, x + 5, y + 15);
      }
   }
}
--------------------------------------------------------
ここで、GeneralPathのmoveTo()メソッドを呼び出し、lineTo()メソッ
ドを2回呼び出し、最後にclosePath()メソッドを呼び出しているのは、
三角形を描いてハエの羽を表現するためです。
このように、閉じた図形を描くためには最後にclosePath()メソッドを
呼び出して図形を閉じます。
また、引数のx、yはハエの座標で、leftwardはハエが左向きかどうか
(右向きならfalse)を表します。



では、続いて、ハエの絵を描画するときのキャンバス(画板)の役割
をするFlyJPanelというビジュアル・クラス(Visual Class)を作成
しましょう。
jp.co.flsi.lecture.flyパッケージの中に作成し、JPanelのサブクラス
とします。
つまり、パッケージ・エクスプローラーの中のJStudy1の中のjp.co.flsi.lecture.fly
を右クリックし、「新規」→「その他」→(「Java」の中の)「Visual Class」
を選択し「次へ」ボタンをクリックし、「名前」欄にFlyJPanelと入力し、
「Style」欄で(Swingの中の)Panelを選択しましょう。また、例によって
「インターフェース」欄にRunnable(java.lang.Runnable)を追加して
おきます。(ハエに動きをつける、つまり、アニメーションにするために
Runnableをimplementsし、マルチスレッドのプログラムにするのです。)
そして、「Inherited abstract methods」にチェック・マークを入れて
おいてから、「終了」ボタンをクリックします。

FlyJPanelのVEエディターが開きましたら、そのソース・コードに下記の
ようなフィールドを追加してください。
--------------------------------------------------------
private int flyX = 100;
private int flyY = 100;
private int agility = 100;
private int velocityBase = 200;
private boolean flyLeftward = false;
private boolean flyAlive = true;
private int panelWidth = 300;
private int panelHeight = 200;
private float ngTimes = 0.0f;
private int score = 0;
--------------------------------------------------------
ここで、flyXはハエのx座標、flyYはハエのy座標、agilityはハエの
敏捷性、velocityBaseはハエが飛ぶ速さの基準、flyLeftwardはハエが
左を向いているかどうか(falseなら右を向いている)を表すフィールド
です。このうちagilityは数値が小さいほど敏捷で、velocityBaseは数値
が大きいほど速いものとします。
また、flyAliveはハエが生きている(撃墜されていない)かどうかを表す
フィールドで、panelWidthはこのパネルの幅、panelHeightはこのパネル
の高さを表します。
ngTimesは無駄撃ちの回数(無駄撃ちは"no good"なのでngという名前を
使っており、timesは回数の意味です)、scoreはゲームの得点を表します。
panelWidthとpanelHeightはハエの移動範囲を制限する(ハエが常に見え
る範囲で飛ぶようにする)ために使用します。


また、panelWidthおよびpanelHeightへのsetter、getterとして下記のよ
うなメソッドを追加しておきましょう。
(「リファクタリング」→「フィールドのカプセル化」の機能を使うと
いいでしょう。)
--------------------------------------------------------
public void setPanelWidth(int panelWidth) {
   this.panelWidth = panelWidth;
}

public int getPanelWidth() {
   return panelWidth;
}

public void setPanelHeight(int panelHeight) {
   this.panelHeight = panelHeight;
}

public int getPanelHeight() {
   return panelHeight;
}
--------------------------------------------------------


続いて、このパネルにFlyPictureを組み込みましょう。
パレットから「Choose Bean」を選択し、「Choose a Bean」ウインドウ
においてFlyPictureを入力して「OK」ボタンをクリックし、パネルの画像
の外側の白いところ(空白のエリア)をクリックすることによって
貼りつけます。
Bean NameはflyPictureのままにしておきましょう。

そうするとgetFlyPicture()というメソッドが自動的に生成されますね。
このメソッドを使えば、FlyPictureのインスタンスを取り出すことが
できます。


続いて、FlyJPanelのソース・コードに下記のようなpaintComponent()
のオーバーライドを行っておきましょう。
--------------------------------------------------------
public void paintComponent(Graphics g) {
   Image image = createImage(getPanelWidth(), getPanelHeight());
   Graphics2D g2dImage = (Graphics2D) image.getGraphics();
   getFlyPicture().drawFly(g2dImage, flyX, flyY, flyLeftward);
   if (!flyAlive)
      g2dImage.drawString("Score = " + score, getPanelWidth()/2, getPanelHeight()/2);
   g.drawImage(image, 0, 0, getPanelWidth(), getPanelHeight(), null);
}
--------------------------------------------------------
このメソッドでは、FlyPictureにハエの絵を描かせていると同時に、
ハエが撃墜されたとき(flyAliveがfalseのとき)には得点(score)
をパネルの中央あたりに表示するようにしています。


続いて、ハエが飛び回る様子を描くためのアニメーションを別のスレッド
にするために、run()メソッド
--------------------------------------------------------
public void run() {
   // TODO 自動生成されたメソッド・スタブ

}
--------------------------------------------------------
を下記のように実装しておきましょう。
--------------------------------------------------------
public void run() {
   double rand;
   float times = 1;
   while (flyAlive) {
      try {
         Thread.sleep(agility);
         rand = Math.random() - 0.5;
         if (flyX < 0) flyX = -flyX;
         if (flyX > getPanelWidth()) flyX -= 100;
         if (flyY < 0) flyY = -flyY;
         if (flyY > getPanelHeight()) flyY -= 100;
         if (rand > 0) flyLeftward = false;
         else flyLeftward = true;
         flyX = flyX + (int) (rand * velocityBase);
         flyY = flyY + (int) ((Math.random() - 0.5) * velocityBase);
         repaint();
      }
      catch (InterruptedException e) {
      }
      times++;
   }
   score = (int) (6000 / times / ngTimes);
   while (flyY < getPanelHeight()) {
      try {
         Thread.sleep(50);
         flyY = flyY + 10;
         repaint();
      }
      catch (InterruptedException e) {
      }
   }
}
--------------------------------------------------------
このメソッドでは、agility=100ミリ秒ごとにハエの新しい座標を
決めていますが、ハエのx座標やy座標が負の値になったりパネルの
境界の外に出たりしたときには境界のなかに収まるように修正し、
ハエが右に移動しているときはflyLeftwardをfalseに、左に移動し
ているときはflyLeftwardをtrueに設定し、あとは乱数に従って次
の座標値を決定しています。
また、最後のwhile (flyY < getPanelHeight())のループは、ハエが
たたかれた後で真っ直ぐ下に墜落していく様子をアニメーションに
するためのものです。

これらは、かなり大雑把なコードなので、ハエの飛び方をもっと
真剣に精密に表現したい人は、自分で工夫してみてください。

得点(score)の計算の仕方も、たんにハエをたたき落とすまでの
経過時間が短く無駄撃ちの回数が少ないほど得点を高くしている
だけで、それ以外は特に意味はなく、いい加減な計算式です。
もっと意味のある計算式にしたい人は自分で工夫してみてください。


続いて、アニメーションを開始したり停止したりするために、下記
のようなメソッドを追加しましょう。
--------------------------------------------------------
public void start() {
   flyAlive = true;
   ngTimes = 0.0f;
   Thread aThread = new Thread(this);
   aThread.start();
}
  
public void stop() {
   ngTimes = Float.POSITIVE_INFINITY;
   flyAlive = false;
}
--------------------------------------------------------
ここで、stop()メソッドにおいてngTimesにFloat.POSITIVE_INFINITY
を代入しているのは、得点を無効(0)にするためです。


次に、パネルのサイズが変更されたときにpanelWidth、panelHeight
が変わるようにするために、以下のようにプログラミングを行って
ください。

(1) 「Java Beans」ビューの「this」を右クリックし、
「Events」→「Add Events」を選択し、「Component」の中の
「componentResized」を選択し、(「Create new Listener」の中の
「extends: java.awt.event.ComponentAdapter」が選択されていること
を確認し)「終了」ボタンをクリックします。

(2) initialize()メソッドの中に自動生成された
--------------------------------------------------------
this.addComponentListener(new java.awt.event.ComponentAdapter() {
   public void componentResized(java.awt.event.ComponentEvent e) {
      System.out.println("componentResized()"); // TODO Auto-generated Event stub componentResized()
   }
});
--------------------------------------------------------
というコードを下記のように編集してください。
--------------------------------------------------------
this.addComponentListener(new java.awt.event.ComponentAdapter() {
   public void componentResized(java.awt.event.ComponentEvent e) {
      setPanelWidth(getBounds().width);
      setPanelHeight(getBounds().height);
   }
});
--------------------------------------------------------
ここで、getBounds()メソッドは、Component(GUI部品)の境界を表す
矩形(Rectangle型)を取り出すためのメソッドで、widthフィールドは
その幅、heightフィールドはその高さの値を持っています。
したがって、上記のコードを使えば、このパネルのサイズが変更された
ときにその変更後の幅や高さがpanelWidthやpanelHeightに設定される
ことになります。



このゲームでは、ハエをたたく行為をマウスのクリックで表現すること
にしますので、マウスをクリックしたときにマウス・ポインターがハエの
絵の上に乗っかっていたかどうかを確認する必要があります。
そして、マウス・ポインターがハエの絵の上に乗っかっていた場合には
flyAliveの値をfalseにします。つまり、ハエが亡くなることにします。
このために、以下のようにプログラミングを行ってください。

(1) 「Java Beans」ビューの「this」を右クリックし、
「Events」→「Add Events」を選択し、「Mouse」の中の「mouseClicked」
を選択し、(「Create new Listener」の中の「extends: java.awt.event.MouseAdapter」
が選択されていることを確認し)「終了」ボタンをクリックします。

(2) initialize()メソッドの中に自動生成された
--------------------------------------------------------
this.addMouseListener(new java.awt.event.MouseAdapter() {
   public void mouseClicked(java.awt.event.MouseEvent e) {
      System.out.println("mouseClicked()"); // TODO Auto-generated Event stub mouseClicked()
   }
});
--------------------------------------------------------
というコードを下記のように編集してください。
--------------------------------------------------------
this.addMouseListener(new java.awt.event.MouseAdapter() {
   public void mouseClicked(java.awt.event.MouseEvent e) {
      Rectangle flyRegion = new Rectangle(flyX, flyY, 18, 15);
      if (flyRegion.contains(e.getX(), e.getY())) flyAlive = false;
      else ngTimes++;
   }
});
--------------------------------------------------------
ここでは、ハエのサイズを大雑把に幅18、高さ15にしています。
そして、この領域内にマウス・ポインターの座標が含まれていれば
flyAliveの値をfalseにしています。
逆に領域内にマウス・ポインターの座標が含まれていなければ無駄撃ち
ということですから、ngTimesを増加しています。



次に、ゲームを開始するためのボタンと途中で停止するためのボタン
を貼り付けることにしましょう。

このパネルに、以下のようにしてJButtonを2つ貼り付けてください。

(1) パネルのレイアウト・マネジャー(LayoutManager)をBorderLayout
にしましょう。つまり、VEエディターのパネルの画像を右クリックし、
「Set Layout」→「BorderLayout」を選択します。

(2) ボタンを貼り付ける土台にするためにJPanelをNorthの位置に貼り
付けましょう。Bean NameはjPanelButtonsにしましょう。

(3) 「Java Beans」ビューの中のjPanelButtonsの上に一つ目のJButton
を貼り付けましょう。Bean NameはjButtonStartにしましょう。
そのtextプロパティーの値を「ゲームの開始」にしましょう。

(3) 「Java Beans」ビューの中のjPanelButtonsの上に二つ目のJButton
を貼り付けましょう。Bean NameはjButtonStopにしましょう。
textプロパティーの値を「ゲームの中止」にしましょう。


続いて、「ゲームの開始」ボタンをクリックしたらゲームが開始する
ようにプログラミングしましょう。以下のように作業してください。

(1) 「ゲームの開始」ボタンを右クリックし、「Events」→「actionPerformed」
を選択します。

(2) getJButtonStart()メソッドに自動生成された以下のコード
--------------------------------------------------------
jButtonStart.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent e) {
      System.out.println("actionPerformed()"); // TODO Auto-generated Event stub actionPerformed()
   }
});
--------------------------------------------------------
を下記のように編集しましょう。
--------------------------------------------------------
jButtonStart.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent e) {
      start();
   }
});
--------------------------------------------------------


続いて、「ゲームの中止」ボタンをクリックしたらゲームが中止する
ようにプログラミングしましょう。以下のように作業してください。

(1) 「ゲームの中止」ボタンを右クリックし、「Events」→「actionPerformed」
を選択します。

(2) getJButtonStop()メソッドに自動生成された以下のコード
--------------------------------------------------------
jButtonStop.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent e) {
      System.out.println("actionPerformed()"); // TODO Auto-generated Event stub actionPerformed()
   }
});
--------------------------------------------------------
を下記のように編集しましょう。
--------------------------------------------------------
jButtonStop.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent e) {
      stop();
   }
});
--------------------------------------------------------


では、保管をしてからテストをしてみましょう。パッケージ・エクス
プローラーの中でFlyJPanelを右クリックし、「実行」→「Java Bean」
を選択してみてください。
「ゲームの開始」ボタンをクリックするとハエが動き始め、
「ゲームの中止」ボタンをクリックするとハエが停止して墜落しますね。
また、途中でパネル(ウインドウ)のサイズを変えて(広げたり縮めたり
して)みても、ちゃんと対応しますね。

一方、ハエを撃墜するのはなかなかむずかしいことがわかりますね。
うまくハエのところにマウス・ポインターをもってこれたと思っても、
クリック(マウスのボタンを押してから離す)の動作の間にハエが動い
てしまうとダメです。ハエが止まっている間にマウスのボタンを押す操作
から離す操作までを完了させなければなりません。
もし、どうしてもハエの動きが速すぎて撃墜できないようであれば、
agilityやvelocityBaseの値を調整してみてください。
動作確認のためには、agilityは1000(1秒間隔でハエが動く)くらい
から始めたほうがいいかもしれません。



では、最後に、このFlyJPanelを使ってゲームを行うためのアプレット
を作りましょう。FlyAppletというクラス名にします。
jp.co.flsi.lecture.flyパッケージの中にFlyAppletをビジュアル・クラス
(Visual Class)として作成しましょう。
つまり、パッケージ・エクスプローラーの中のJStudy1の中のjp.co.flsi.lecture.fly
を右クリックし、「新規」→「その他」→(「Java」の中の)「Visual Class」
を選択し「次へ」ボタンをクリックし、「名前」欄にFlyAppletを入力し、
「Style」欄で(Swingの中の)Appletを選択し、「終了」ボタンをクリック
します。

FlyAppletのVEエディターが開きましたら、アプレットの(初期)サイズ
を変更しておきましょう。
init()メソッドのソース・コードの中の
--------------------------------------------------------
this.setSize(300, 200);
--------------------------------------------------------
の行を
--------------------------------------------------------
this.setSize(600, 400);
--------------------------------------------------------
などに編集し、アプレットのサイズを大きめにしておきます。


続いて、このアプレットにFlyJPanelを貼り付けることにしましょう。
パレットから「Choose Bean」を選択し、「Choose a Bean」ウインドウ
においてFlyJPanelを入力して「OK」ボタンをクリックし、アプレット
の画像の中のCenterの位置に貼り付け(クリック)してください。
Bean NameはflyJPanelのままにしておきましょう。


これで、今回のゲーム・ソフトは完成です。
保管してFlyAppletを起動し、テストしてみてください。


では、今回はここまでにします。なお、今回作成したアプレットも
ホームページにも掲載しておきますので、完成したアプレットの動き
を確認したい人は下記ホームページのvol.066の項目から実行してみて
ください。

http://www.flsi.co.jp/Java_text/

何か、わからないところがありましたら、下記のWebページまで質問を
お寄せください。


(続く)



========================================================
◆ 02.Java(文法等)解説 [JavaBeans (1)]
========================================================

[JavaBeansの概要]

JavaBeansというのは、Javaのクラスを部品化し、ビルダー・ツール
(builder tool = プログラムをビジュアル(visual = 視覚的)に構築
するツール)で部品をビジュアルに操作することによってプログラム
を構築できるようにすることを目的として作られた技術です。

JavaBeansという名前は、この技術仕様の名前であり、JavaBeansに
おける部品のことをBean(複数形はBeans)と呼びます。
JavaのBeanというときは単数形(ただし、英語では複数個あれば複数形)
ですが、仕様名は必ずJavaBeansと、複数形にしますので、間違えないで
ください(間違えたからって、罰則があるわけではありませんが)。

JavaBeansを最大限に利用した代表的なビルダー・ツールとしては、IBM
のVisualAgeという製品に含まれるビジュアル・コンポジション・エディ
ターというものがありました。
このツールは、既存のBeanをツール上に配置させ、Bean同士をビジュアル
に線でつなぎ合わせるだけでプログラムが作れるというもので、極めて
生産性の高いものでしたが、残念ながらあまり普及しませんでした。
あまりにも従来のプログラミング手法と違いすぎるために、従来型のプロ
グラマーにはとっつきにくかった(習得しにくかった)ことが原因だと
思われますが、結局この製品は無くなりました。
しかし、実はEclipseは元々このVisualAgeを改築して作られたツール
なのです。
残念ながら、ビジュアル・コンポジション・エディターは無くなりました
が、他のいくつかの機能がEclipseの中に引き継がれています。


このように、JavaBeansによってビジュアルにプログラムを構築するプロ
グラミング手法自体は普及しませんでした(ただし、Visual Editorの
ようにビジュアルに部品を貼り付けるという程度の手法なら普及して
います)が、JavaBeansが持つさまざまな技術は現在でも有効利用され
ています。


そこで、今回から、現在でも有効利用されているJavaBeansの技術を
少しずつ解説していきたいと思います。

まず最初に、Beanが持っている主な機能として、以下のものを概観して
いきましょう。

・Beanが持つフィーチャー(feature = 機構)
   イベント、プロパティー、メソッド
・イントロスペクション(introspection)
   Beanが持つフィーチャーをBeanの外から調べる機能
・シリアライゼーション(直列化:serialization)
   Beanの状態をファイルなどに保管したり、逆に復元したりする機能
   あるいはネットワークを通してBeanの状態をやり取りすることもできる。


Beanの元々の意味は豆です。Javaの名前がジャワ・コーヒーから来ている
ことから、Beanという名前もコーヒー豆に由来します。
コーヒー豆がコーヒーの原料であるように、Javaにおける部品のことを
Beanと呼ぶことにしたのです。

部品のことをコンポーネント(Component)と呼ぶことがありますが、
JavaにおいてはComponentはGUI部品のクラス名になっていますので
注意してください。
Beanと言った場合は、GUI部品(Component)だけでなく、GUI以外の
一般のクラスも含みます。


では、クラスならなんでもBeanと呼べるかというとそうではなく、Bean
と呼ばれるためにはそのクラスが最低限でも以下の特徴を持っている
必要があります。

(1) フィーチャー(イベント、プロパティー、メソッド)を持っている
  こと。
(2) publicなデフォルトのコンストラクター(引数のないpublicなコン
  ストラクター)を持っていること。
(3) イントロスペクションの機能を提供すること。



(1) Beanのフィーチャーの概観

まず最初に、Beanはイベント(event)、プロパティー(property)、
メソッド(method)のいずれかのフィーチャー(feature = 機構)を持っ
ていなければなりません。これらのフィーチャーはBeanが外部のオブジェ
クトとやり取りするために必要なものであり、イベントもプロパティーも
メソッドもどのフィーチャーも持っていないクラスは無用のものとなって
しまい、存在する価値自体がなくなってしまいます。


このうち、イベントというのは今までに頻繁に出てきましたが、何らかの
事象を通知する機構です。

プロパティーというのは、簡単にいうとオブジェクト指向における属性
のことだと思えばいいのですが、ただし、正確にいうと属性を表すのは
フィールドであり、プロパティーは、そのフィールドに値を設定したり
値を取り出したりする、setter、getterなどのメソッドを含めた機構の
名称です。
むしろ外からは見えないフィールドなどは重要ではなく、publicな
setterやgetterを実装することによって、はじめてプロパティーが提供
されたことになります。

メソッドというのは、ずばりオブジェクト指向におけるメソッドのこと
です。プロパティーのsetterやgetterを除く、一般のメソッドのことを
意味しますが、ただし、Beanのフィーチャーとしてのメソッドは外部の
オブジェクトとやり取りするためのものであるため、publicなものに
限られます。


(2) publicなデフォルトのコンストラクター

Beanはビルダー・ツールやサーブレット、JSPなどによって、デフォルト
のコンストラクター(引数なしのコンストラクター)が呼び出されてイン
スタンスが生成されます(詳しくは後述)。
そのために、publicなデフォルトのコンストラクターが必ず必要になります。

コンストラクターの定義が一切ない場合にはJavaコンパイラーが自動的に
デフォルトのコンストラクターを生成してくれるので問題ないのですが、
引数つきのコンストラクターを定義した場合には、必ずデフォルトのコン
ストラクターも明示的に定義しておく必要があります。なお、デフォルト
のコンストラクターには外部からアクセスできる必要があります(ビルダー・
ツールやサーブレット、JSPなどからアクセスされる)から必ずpublic指定
でなければなりません。


(3) イントロスペクションの概観

イントロスペクションは、Beanが持つフィーチャーを外部から認識できる
機能であり、この機能はビルダー・ツールなどによって使用されます。
この機能を提供するためには、以下のいずれかのルールに従う必要があり
ます。

・フィーチャーの名前が一定の命名規則に従っていること。
・BeanInfoと呼ばれるクラスを実装していること。

BeanInfoが用意されている場合は、BeanのフィーチャーはBeanInfoを通して
認識されますが、BeanInfoが用意されていない場合は、Beanのフィーチャー
はリフレクションという仕組みを通して命名規則に従って認識されます。

リフレクション(reflection)というのは、プログラムの実行時にクラス
のフィールドやメソッドを調べる仕組みであり、この仕組みを使えば、
実行時にそのクラスがどのようなメソッドを持っているのかを調べて、
そのメソッドを実行することもできます。
ビルダー・ツールだけでなく、一般のプログラマーもリフレクションの
仕組みを利用することができます(詳しくは後述)。



(続く)



以上、今回は
┌───────────────────────────┐
・GeneralPathを使った閉じた図形(今回は三角形)の描き方
・Component(GUI部品)の境界の取得方法(getBounds())
・Componentの境界からサイズを取得する方法(getBounds().width、
 getBounds().height)
・Componentのサイズが変更されたときに処理を実行する方法
 (ComponentListener(今回はComponentAdapter)の
  componentResized()メソッドを実装。および、Componentの
  addComponentListener()メソッドでComponentに登録)
└───────────────────────────┘
を学習しました。
では、また来週。



================================================
◆ 03.演習問題
================================================

上記のハエたたきゲームにおいて、agilityフィールドやvelocityBase
フィールドの値をユーザーが変更できるように、プログラミングして
みてください。(たとえば、JTextFieldで数値を入力できるようにし、
JButtonをクリックすると入力した値がフィールドに代入されるように
します。)



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2007 Future Lifestyle Inc. 不許無断複製