広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2012年02月04日

   Java総合講座 - 初心者から達人へのパスポート
                 2009年11月開講コース 056号

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


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:vol.xxx(xxxは番号)が振られています。
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


========================================================
◆ 01.グラフィックスのプログラミング
========================================================

では、線の色や太さを変えられるようにするために、DrawingPanelの
ソース・コードに次のメソッドを追加しましょう。

--------------------------------------------------------
public void setDrawColor(Color c) {
   lineColor = c;
}

public void setDrawStroke(Stroke s) {
   drawStroke = s;
}
--------------------------------------------------------


保管が終わったら、このDrawingPanelをもう一つ別のJPanel(のサブクラス)
(DrawingToolPanelという名前にします)に貼り付けることにします。

DrawingToolPanelはDrawingPanelを貼り付けるだけでなく、054号で貼り付け
たように色を選択するためのトグル・ボタン(JToggleButton)などのツール
(道具)類も貼り付けます。したがって、名前にToolという単語を含ませて
います。

========================================================

では、下記の手順でDrawingToolPanelを作っていきましょう。

(1) パッケージ・エクスプローラーの中のJStudy1の配下のsrcの配下の
jp.co.flsi.lecture.cg(パッケージ名)を右クリックし、
「新規」→「その他」を選択します。

(2) 「新規」ウインドウにおい「WindowBuilder」配下の
「Swing Designer」配下の「JPanel」を選択し、「次へ」ボタンを
クリックします。

(3) 「New JPanel」ウインドウにおいて「ソース・フォルダー」欄に
「JStudy1/src」が入力されていることを確認し、「パッケージ」欄に
「jp.co.flsi.lecture.cg」が入力されていることを確認し、
「名前」の欄に

DrawingToolPanel

と入力し、「完了」ボタンをクリックします。

DrawingToolPanelのエディターが開いたら、Designビューを開きましょう。

(4) まず、このJPanelをBorderLayoutにしておきましょう。そのためには、
画面上のJPanelの部分(灰色の部分)をクリックすると、左側のProperties欄
にプロパティーがリストされるので、そのうちのLayoutの右側の逆三角形マーク
のボタンをクリックし、BorderLayoutを選択します。

BorderLayoutにしておくと、GUI部品を貼り付ける位置がNORTH、SOUTH、
WEST、EAST、CENTERと、5箇所に分かれるのでしたね。そこで、WESTの位置
にトグル・ボタンなどのツール類を貼り付け、CENTERの位置にDrawingPanel
を貼り付けることにします。ただし、WESTの位置にボタンなどを複数貼り
付けられるようにするために、まずはWESTの位置に、それらの土台となる
JPanelを貼り付けておくことにします。

(5) PaletteのContainers配下のJPanelを選択し、BorderLayoutのWEST側
(左端の部分)に貼り付けます。(これは後でトグル・ボタンなどを貼り
付けるための土台にするものです。)

(6) PaletteのSystem配下のChoose componentをクリックし、「型を開く」ウインドウ
において「Select a type to add」欄に

DrawingPanel

と入力し(途中まで入力すればその下にリストが出てくるから、その中から
選択すればよい)、「OK」ボタンをクリックして、BorderLayoutのCENTER側
(中央の部分)に貼り付けます。
変数名(Properties欄のVariable)はdrawingPanelのままにしておきますが、
このdrawingPanelという変数名はあとで使いますので覚えておきましょう。

このように、Paletteの中にリストされていないGUI部品(DrawingPanelは
自作のクラスだから当然Paletteの中にはリストされていない)であっても
System配下のChoose componentをクリックすることによって選択することが
できるのです。


では続いて、先ほどWEST側に貼り付けたJPanelを土台にして、以下のように
トグル・ボタン等を貼り付けていきましょう。

(7) まず、このWEST側のJPanelのLayoutManagerをnullにしておきましょう。
(このWEST側のJPanelをクリックすることによって選択した後、Properties欄
のLayoutの値をFlowLayoutからAbsolute layoutに変更(右側の逆三角形マーク
のボタンを押してリストから選択)します。)

すると、このJPanelの幅がペシャンコになってつぶれてしまいますので、以下
のようにして幅を広げておきましょう。

(8) このWEST側のJPanelを選択(Structure配下のComponents欄の中にリストさ
れているpanelをクリックするとよい)し、Properties欄のpreferredSizeプロパティー
(preferredSizeプロパティーは予めProperties欄の右側の「Show advanced properties」
ボタン(Properties欄の右側にたくさん並んでいるボタンのうち右から2つ目の
ボタン。ボタンにマウスを乗せれば「Show advanced properties」という文字列
が表示されるもの)をクリックしておかなければ表示されないので注意)の右側
の「・・・」ボタンをクリックし、幅に125と入力して「OK」ボタンをクリックしま
しょう。

(9) 次にPalette(パレット)から(Componentsの)JToggleButtonを取り出して
このWEST側のJPanelに貼り付けましょう。
変数名(Properties欄のVariable)はredToggleButtonにしておきましょう。

(10) このredToggleButtonの下にさらにJToggleButtonを2つ貼り付け、
それぞれgreenToggleButtonおよびblueToggleButtonという変数名にして
おきましょう。
つまり、JToggleButtonが全部で3個、縦に並ぶように貼り付けるわけです。


続いて、以下のようにして、これらのJToggleButtonに色を付けましょう。
また、色の文字を表示させるようにしましょう。

(11) redToggleButtonをクリック(あるいはStructure欄のredToggleButton
を選択)することによって、Properties欄にredToggleButtonのプロパティー
を表示させます。

(12) その中のbackgroundプロパティーを選択し、その右端のボタンをクリックし、
「Color chooser」ウインドウの中の「AWT colors」タブを選択して
色のリストの中から「RED」を選択し、「OK」ボタンをクリックします。
(これでボタンに色が付いたはずですが、エディター上では色は見えません。)

(13) textプロパティーの値を「赤」に設定しましょう。

(14) サイズが小さいと「赤」という文字が表示されませんから、文字が表示
されるように四隅のハンドルをドラッグしてJToggleButtonのサイズを大きく
しておいてください。

(15) 同様にして、greenToggleButtonのbackgroundプロパティーを「GREEN」、
textプロパティーの値を「緑」に、blueToggleButtonのbackgroundプロパティー
を「BLUE」、textプロパティーの値を「青」にしてください。


続いて、線の太さを選択できるようにするためのGUI部品を貼り付けることに
しましょう。今度はJListというGUI部品を使うことにします。

(16) Paletteから(Components配下の)JListを取り出して色ボタン(「青」ボタン)
の下に貼り付けてください。変数名はstrokeListにしましょう。

(17) 貼り付いたstrokeListは点のようにつぶれた状態になっているでしょうから、
適当な大きさに(ドラッグして)広げてください。
(strokeListがどこへ行ったかわからなくなった人は、Structure配下のComponents欄
のリストの中にあるstrokeListをクリックすれば、strokeListが選択状態になります。)
また、先ほどの(トグル・ボタンやJListを貼り付けた土台になっている)JPanel
のときと同様にしてstrokeListのpreferredSizeを幅125、高さ60にしておきま
しょう。


(18) 上記の3つのトグル・ボタンのうち、最初はblueToggleButtonが選択されて
いる状態にしたいので、blueToggleButtonをクリックし、Properties欄の
selectedプロパティーを選択して、その値をtrueに変更してください。
(デフォルトではfalseが表示されているはずですが、そこをダブル・クリック
するとチェック・マークが付きtrueに変わります。)


これら3つのJToggleButtonは、ラジオ・ボタンのように同時に一つだけ
しか選択できないようにしたいので、以下の手順で、これらを一つの
ButtonGroupに登録することにしましょう。

(19) ソース・コード上で
      JToggleButton redToggleButton = new JToggleButton("\u8D64");
という行を探し、この中のredToggleButtonという変数にカーソルを入れ、
メニュー・バーから「リファクタリング」→「ローカル変数をフィールドに変換」
を選択します。

(20) 「ローカル変数をフィールドに変換」ウインドウで「OK」ボタンを
クリックします。
以上でredToggleButton変数が他のメソッドからもアクセス可能になります。

(21) 同様の操作(上の(19),(20))を、
      JToggleButton greenToggleButton = new JToggleButton("\u7DD1");

      JToggleButton blueToggleButton = new JToggleButton("\u9752");
の行に行うことによって、greenToggleButtonとblueToggleButtonもフィールド
に変換しておきます。

(22) 下記のようなコードをコンストラクターDrawingToolPanel()の末尾に
追加します。

なお、ButtonGroupクラスはjavax.swingパッケージにはいっています。

--------------------------------------------------------
      ButtonGroup group = new ButtonGroup();
      group.add(redToggleButton);
      group.add(greenToggleButton);
      group.add(blueToggleButton);
--------------------------------------------------------

ここではButtonGroupのadd()メソッドの呼び出しによって、redToggleButtonと
greenToggleButtonとblueToggleButtonの3つのToggleButtonを一つのButtonGroup
に登録してグループ化しています。


次に、strokeListの中に選択項目を組み込みこんでおきましょう。
ここでは、「太さ1」、「太さ2」、「太さ5」という3つの選択項目
を組み込むことにします。

以前(036号や046号などで)お話ししたように、SwingではSwingのUIオブジェクト
とモデル・オブジェクトを分離するという考え方があり、JListはListModelという
インターフェースを実装したモデル・オブジェクトにデータを入れて使用する
ことができます。
これは、046号で紹介したJTableの場合と同様のやり方になります。

しかし、今回は選択項目が少ないので、もっと安直なやり方を取る
ことにします。

(23) では、下記のようなコードをコンストラクターDrawingToolPanel()の末尾に
追加してください。

--------------------------------------------------------
      Vector<String> stroke = new Vector<String>();
      stroke.add("太さ1");
      stroke.add("太さ2");
      stroke.add("太さ5");
      strokeList.setListData(stroke);
--------------------------------------------------------

このように、JListに表示したい文字列をVectorに保管しておき、そのVectorを
JListのsetListData()というメソッドでセットしておくと、Vectorに保管
されている文字列がその順番でJListに表示されることになります。

念のために、現時点のコンストラクター全体のコードを下に提示しておきます。

--------------------------------------------------------
   public DrawingToolPanel() {
      setLayout(new BorderLayout(0, 0));

      JPanel panel = new JPanel();
      panel.setPreferredSize(new Dimension(125, 10));
      add(panel, BorderLayout.WEST);
      panel.setLayout(null);

      redToggleButton = new JToggleButton("\u8D64");
      redToggleButton.setBackground(Color.RED);
      redToggleButton.setBounds(0, 23, 125, 21);
      panel.add(redToggleButton);

      greenToggleButton = new JToggleButton("\u7DD1");
      greenToggleButton.setBackground(Color.GREEN);
      greenToggleButton.setBounds(0, 64, 125, 21);
      panel.add(greenToggleButton);

      blueToggleButton = new JToggleButton("\u9752");
      blueToggleButton.setSelected(true);
      blueToggleButton.setBackground(Color.BLUE);
      blueToggleButton.setBounds(0, 111, 125, 21);
      panel.add(blueToggleButton);

      DrawingPanel drawingPanel = new DrawingPanel();
      add(drawingPanel, BorderLayout.CENTER);

      JList strokeList = new JList();
      strokeList.setPreferredSize(new Dimension(125, 60));
      strokeList.setBounds(0, 153, 125, 60);
      panel.add(strokeList);

      ButtonGroup group = new ButtonGroup();
      group.add(redToggleButton);
      group.add(greenToggleButton);
      group.add(blueToggleButton);

      Vector<String> stroke = new Vector<String>();
      stroke.add("太さ1");
      stroke.add("太さ2");
      stroke.add("太さ5");
      strokeList.setListData(stroke);
   }
--------------------------------------------------------


では次に、「赤」「緑」「青」のボタンをクリックしたときに線の色が
変わるようにプログラミングしましょう。

線の色を変えるためには、drawingPanelのsetDrawColor()メソッドを
呼び出す必要があります。
ところが、このdrawingPanelは現時点ではDrawingToolPanelのコンストラクター
の中でローカルな変数として定義されてしまっていますね。
これでは他のメソッドからdrawingPanelにアクセスすることができないので、
予めdrawingPanelを変数からフィールドに変更しておきましょう。

(24) そのためには、ソース・コードの中でdrawingPanel変数を定義している行、
すなわち

      DrawingPanel drawingPanel = new DrawingPanel();

という行を探し、その中のdrawingPanelの中にカーソルを入れ、メニュー・バー
から、「リファクタリング」→「ローカル変数をフィールドに変換」を選択し、
「ローカル変数をフィールドに変換」ウインドウで「OK」ボタンをクリック
します。
これで、drawingPanelがフィールドに変わりました。


では続いて、「赤」のボタンをクリックしたときに線の色が赤くなるように
プログラミングしましょう。

(25) まず、Designビューの中でredToggleButtonを右クリックして、
「Add event handler」→「アクション」→「actionPerformed」
を選択します。

すると、ソース・コードに以下のコードが自動的に追加されますね。

--------------------------------------------------------
      redToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
         }
      });
--------------------------------------------------------

これを以下のように編集しましょう。

--------------------------------------------------------
      redToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            drawingPanel.setDrawColor(new Color(255,0,0));
         }
      });
--------------------------------------------------------


(26) 「緑」のボタンと「青」のボタン、つまり、greenToggleButton
とblueToggleButtonに対しても、同様に操作して、それぞれ、

--------------------------------------------------------
      greenToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
               drawingPanel.setDrawColor(new Color(0,255,0));
         }
      });
--------------------------------------------------------

--------------------------------------------------------
      blueToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
               drawingPanel.setDrawColor(new Color(0,0,255));
         }
      });
--------------------------------------------------------

というように編集しましょう。


では続いて、strokeListの中のどれかの項目を選択すると、drawingPanelに
描画する線の太さを変更するようにプログラミングしましょう。
線の太さを変更するにはdrawingPanelのsetDrawStroke()メソッドを実行する
必要があります。

その前に、strokeListもやはり先ほどのdrawingPanelと同じく、ローカル変数
として定義されているので、これも予めフィールドに変換しておきましょう。

(27) そのためには、ソース・コードの中でstrokeList変数を定義している行、
すなわち

      JList strokeList = new JList();

という行を探し、その中のstrokeListの中にカーソルを入れ、メニュー・バー
から、「リファクタリング」→「ローカル変数をフィールドに変換」を選択し、
「ローカル変数をフィールドに変換」ウインドウで「OK」ボタンをクリック
します。
これで、strokeListがフィールドに変わりました。


では、このstrokeListの中のどれかの項目を選択すると線の太さを変える
(drawingPanelのsetDrawStroke()メソッドを呼び出すことによって、
その線の太さをdrawingPanelに設定する)ようにプログラミングしま
しょう。

(28) DesignビューでstrokeListを右クリックし、
「Add event handler」→「listSelection」→「valueChanged」
を選択します。

(29) すると、ソース・コードに以下のコードが自動的に追加されますね。

--------------------------------------------------------
      strokeList.addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
         }
      });
--------------------------------------------------------

JList上で選択する項目が変わると、このListSelectionListener
のvalueChanged()メソッドが呼び出されることになります。

このコードを下記のように編集しましょう。

--------------------------------------------------------
      strokeList.addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
            switch (strokeList.getSelectedIndex()){
            case 0:
               drawingPanel.setDrawStroke(new BasicStroke(1f));
               break;
            case 1:
               drawingPanel.setDrawStroke(new BasicStroke(2f));
               break;
            case 2:
               drawingPanel.setDrawStroke(new BasicStroke(5f));
               break;
            }
         }
      });
--------------------------------------------------------

はい。これで線の太さを変えるための実装は完了です。


以上で、線の色や太さを変えながらお絵描きできるようになりました。
しかしながら、このDrawingToolPanelはGUI部品に過ぎません。
このままでは、アプリケーションでもアプレットでもないので、実行は
できません。(ただし、Eclipse上ではJava Bean単独の実行もできます
が、これはテスト用のものであって、本番稼働はできません。)

========================================================

そこで、このDrawingToolPanelをアプレットに貼り付けて、アプレット
として実行できるようにしましょう。

アプレットはDrawingToolAppletという名前にしましょう。

(1) パッケージ・エクスプローラーの中のJStudy1の配下のsrcの配下の
jp.co.flsi.lecture.cg(パッケージ名)を右クリックし、
「新規」→「その他」を選択します。

(2) 「新規」ウインドウにおい「WindowBuilder」配下の
「Swing Designer」配下の「JApplet」を選択し、「次へ」ボタンを
クリックします。

(3) 「New Swing JPanel」ウインドウにおいて「ソース・フォルダー」欄
に「JStudy1/src」が入力されていることを確認し、「パッケージ」欄に
「jp.co.flsi.lecture.cg」が入力されていることを確認し、
「名前」の欄に

DrawingToolApplet

と入力し、「完了」ボタンをクリックします。

DrawingToolAppletのエディターが開いたら、Designビューを開きましょう。

(4) まず、このアプレットをBorderLayoutにしておきましょう。そのためには、
画面上のアプレットのお腹の部分(灰色の部分)を右クリックし、
「Set layout」→「BorderLayout」を選択します。(先ほどやったように
Properties欄のLayoutの右側の逆三角形マークのボタンをクリックし、
BorderLayoutを選択するという方法でもよい。)

(5) PaletteのSystem配下のChoose componentをクリックし、「型を開く」ウインドウ
において「Select a type to add」欄に

DrawingToolPanel

と入力してDrawingToolPanelを選択し、「OK」ボタンをクリックして、
BorderLayoutのCENTER側(中央の部分)に貼り付けます。
(変数名はdrawingToolPanelのままにしておきます。)

これで完成です。


では、このDrawingToolAppletを保管して実行してみてください。
アプレットの実行ですから、DrawingToolAppletを右クリックし、
「実行」→「Javaアプレット」を選択するのでしたね。

絵を描いてから最小化し、再度表示すると、ちゃんと絵が再現されます
ね。それから色のボタンや太さのリストを選択するとその色や線の太さ
で絵が描けることも確認できますね。




ところで、DrawingPanelのソース・コードの先頭のほうを見ると

   private Point startPoint = null;
   private Point endPoint = null;

という2行に警告のマーク(左端に小さな黄色い電球と!のマークが付き、
startPointとendPointに黄色いアンダー・ラインが引かれている)が付いて
いますね。

その警告マークにマウス・ポインターを乗せると
「フィールドXXXXはローカルで読み取られません」
というメッセージが表示されます。
これは、これらのフィールドがどこからも参照されていない(使われていない)
ことを意味します。

使われもしないフィールドを定義しておくのは無駄で邪魔だし、間違いのもと
(あとで、間違えて使ってしまってバグの元になる恐れがある)なので、要ら
ないものは削除すべきです。

しかし、このstartPointとendPointというフィールドは実は、あとで直線や
矩形や楕円などの図形を描けるようにするために先行して定義しておいた
ものです。
というわけで、削除せずにそのまま残しておいて下さい。
これらは次回以降に使用します。

(ちなみに、クラス名のDrawingPanelにも警告のマークが付いていますが、
こちらはマウス・ポインターを乗せると
「シリアライズ可能クラス・・・・・static final serialVersionUIDフィールド
を宣言していません」
というメッセージが表示されますね。これについては039号などを参照して
下さい。)


今回はここまで。


(続く)



========================================================
◆ 02.文法解説 [アプレット]
========================================================

[アプレット(2)「アプレットのメソッド」]

アプレットはアプリケーションと異なり、main()メソッドを使用しません。
Appletクラスにはmain()メソッドの代わりに下記の4つのメソッドが用意さ
れています。

(1)  init()メソッド[ public void init() ]
アプレットを含むWebページがWebブラウザーによって読み込まれ表示される
ときにアプレットがメモリー上にロードされ起動されますが、そのときに
1回だけinit()メソッドが実行されます。
init()はアプレットのデータの初期設定作業などに使用されます。
Appletクラスのinit()メソッドは何もしません。必要ならばAppletのサブ
クラスでinit()メソッドを上書きして実装します。

(2)  start()メソッド[ public void start() ]
start()メソッドはinit()メソッドが実行された後に実行されます。
また、Webブラウザーがいったん他のWebページを開くことによって、アプ
レットが含まれているWebページが表示されなくなった後、再度アプレット
が含まれているWebページが表示されると、その時点でもstart()メソッド
が実行されます。
音楽やアニメーションなどを流すアプレットではstart()メソッドでそれら
を開始するように実装することが多いです。
Appletクラスのstart()メソッドは何もしません。必要ならばAppletのサブ
クラスでstart()メソッドを上書きして実装します。

(3)  stop()メソッド[ public void stop() ]
stop()メソッドは、Webブラウザーがいったん他のWebページを開くことに
よって、アプレットが含まれているWebページが表示されなくなったときに
実行されます。
また、Webブラウザーを終了したときなど、Webページが解放されるときにも
実行されます。
音楽やアニメーションなどを流すアプレットではstop()メソッドでそれらを
停止するように実装することが多いです。
Appletクラスのstop()メソッドは何もしません。必要ならばAppletのサブク
ラスでstop()メソッドを上書きして実装します。

(4)  destroy()メソッド[ public void destroy() ]
destroy()メソッドはWebブラウザーを終了したときなど、Webページが解放
されるときに、stop()メソッドの実行後に実行されます。
アプレットのデータの後始末作業などに使用されます。
Appletクラスのdestroy()メソッドは何もしません。必要ならばAppletのサ
ブクラスでdestroy()メソッドを上書きして実装します。

なお、アプレットが含まれているWebページを表示した後、Webブラウザーの
リロード・ボタン(「更新」ボタン)をクリックしたときには、
stop()→destroy()→Webページの再読み込み→init()→start()の順に実行
されることになります。


(続く)



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

DrawingToolPanelのstrokeListに別の線の太さを追加してプログラム
を改良してみてください。


(続く)



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      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) 2012 Future Lifestyle Inc. 不許無断複製