目次> 第16章> 16.3 TOPUPPREVNEXT

16.3 ドロー系とペイント系

描画を保存して再描画したり、修正したりする方式に の2種類があります。

描画対象を取り扱うのに便利なクラスに Graphics2D と RectangularShape があります。 Ellipse2D.Double(楕円) と Rectangle.Double(矩形)を書く例を提示します。

この『楕円(や矩形)を書く』方法は、前節の swing コンポーネントへの描画とは少しニュアンスが異なります。 前節では例えば、
『(x,y)を左上隅にする幅w、高さh の矩形に内接する楕円を描け』
と命令したのですが、ここでは
『(x,y)を左上隅にする幅w、高さh の矩形に内接する楕円』を生成しておき、『それ』を描け、と命令します。

Graphics2D と Ellipse2D.Double(楕円)、Rectangle.Double(矩形)のクラス階層は次の通り。


  java.lang.Object
   ├ java.awt.Graphics
   │    └ java.awt.Graphics2D
   └ java.awt.geom.RectangularShape
         ├ java.awt.geom.Ellipse2D
         │    └ java.awt.geom.Ellipse2D.Double
         └ java.awt.geom.Rectangle2D
               └ java.awt.geom.Rectangle2D.Double
  

イメージとして扱うには、BufferedImage クラスを使います。

【例1】 楕円と矩形を RectangularShape の配列として保存する方法(ドロー)

paintComponent で描画しなければいけないものを RectangularShape の配列に保存しておき、 paintComponent がよばれたら、Graphics2D の draw メソッドで描画すると言う方法です。

page-16-4.gif

ソース・プログラム Graph2d.java

描画の手順

  1. java.awt.geom.* を import しましょう。(4行目)
  2. Ellipse2D.Double と Rectangle2D.Double の親クラス RectangularShape の配列 shape(14行目) と 要素の個数 nshape (13行目)を定義します。
  3. コンストラクタの中で、マウスリスナを登録します。 ここでは、アダプタをつかった方法を用います。 オーバライドが必要な mouseReleased だけを定義するだけですみます。(17〜36行目)
  4. マウスカーソルの位置を取得し、double に変換(19〜20行目)
  5. 画面の下端に貼り付けたテキストフィールドから 図形の幅と高さをとりだし、double に変換(21〜22行目)
  6. 画面の下端のラジオボタンで指定された図形(楕円か矩形)を 生成し、s に代入(23〜28行目)
  7. 保存用の配列に s を代入(29〜33行目)
  8. 描画(34行目)
  9. paintComponent メソッドを定義します。(40〜47行目)
  10. g を Graphics2D に変換(42行目)
  11. gg に対して配列に保存した図形を draw します(45行目)。
  12. ラジオボタンをボタングループに登録し(69〜71行目)、 パネルに貼り付けます(72〜74行目)。
  13. ラベルで標題をつけて、テキストフィールドを貼り付けます(75〜78行目)。

クリックをした場所を左上隅にする図形が表示されます。

【例2】 描いた図形を BufferedImage として保存する方法(ペイント)

BufferedImage に描画しておき(書きためておき)、 paintComponent が呼ばれたら、その BufferedImage を画面にコピーする方法です。

page-16-5.gif

ソース・プログラム Graph2p.java

描画の手順

  1. java.awt.image.BufferedImage を import しましょう。(5行目)
  2. BufferedImage クラスの変数 image と、image のGraphics2D を保持する imageGraphics を宣言します。(13〜14行目)
  3. コンストラクタの中で、マウスリスナを登録します。(17〜31行目)
    x、y、w、h の取得方法は例1と同じです。
  4. 画面の下端のラジオボタンで指定された図形(楕円か矩形)を 生成し、shape に代入(24〜28行目)
  5. 描画(29行目)
  6. paintComponent メソッドを定義します。(35〜51行目)
  7. 初回の描画のときは、このパネルの大きさと同じイメージを生成し、 image という名前をつけ(37〜40行目)、image の Graphics を 作成し、背景色で塗りつぶしておきます(41〜43行目)。
  8. shape に図形が設定されていればそれを image に描画します。(46〜48行目) できた image をこのパネルに書き出します(49行目)。
  9. main メソッドは例1と同じです。
ペイント系の描画については 16.7 以降に例題があります。 この節では、以降ドロー系の描画の例を掲げます。

【例3】 描いた図形の移動(ドロー その2)

ドロー系の例として、描いた図形をマウスで移動してみましょう。

例1のプログラムに次のような変更を加えます。 行番号は プログラム Graph2d1.java の該当個所。

ソースプログラム Graph2d1.java

実行例

page-16-8.gif

【例4】 色つき図形

色のついた図形を描画しましょう。 色の選択は、Appendix A Component の java.swing.JColorChooser の showDialog の使用例 (プログラム ColorButton6.java) を参考にします。

楕円や矩形の親クラス RectangularShape を継承するか委譲するかして、色付きのクラスを作ることになります。 つまり、


  class ColoredShape extends RectangularShape { // 継承
      Color color;
      ...
  }
  
とするか、

  class ColoredShape {
      RectangularShape shape;                   // 委譲
      Color color;
      ...
  }
  
とするかのいずれかの方法があります。 ColoredShape と RectangularShape の関係が is-a 関係とも has-a 関係ともいえますので(注1) いずれの方法でもよいのですが、 ここでは後者のやり方を採用しました。前者のやり方は例5で挑戦しましょう。
注1
is-a : ColoredShape は RectangularShape に Color 属性を追加したもの
has-a : ColoredShape は RectangularShape 属性 と Coror 属性をもっている

例3のプログラムに次のような変更を加えます。 行番号は プログラム Graph2d2.java の該当個所。

ソースプログラム Graph2d2.java

Graph2d1.java との差異 (例3の Graph2d1.java からの変更個所を赤色で表示)

実行例

page-16-9.gif

【例5】 色つき図形(interface の拡張)

RectangularShape が抽象クラスですので、単に extends RectangularShape とすると、 コンストラクタを自分で書くはめになります。 ここででは、interface Shape を拡張して、getColor() が使えるようにしておいて、 Ellipse2D.Double を継承したクラスと Rectangle2D.Double を継承したクラスを 定義しました。
インターフェースの拡張はこの講座の範囲外ですが、プログラムを提示しておきます。

ソースプログラム Graph2d2x.java

実行結果は例4と同じです。

Graph2d1.java との差異 (例3の Graph2d1.java からの変更個所を赤色で表示)

【例6】 色つき図形(interface の拡張)

【例5】でinterface Shape を拡張して、getColor() を追加しましたが、 color を外に出さないようにして、自分自身を描画する機能をもたせてしまいましょう。

ソースプログラム Graph2d2y.java

実行結果は例4と同じです。

Graph2d2x.java との差異 (例3の Graph2d2x.java からの変更個所を赤色で表示)

【例7】 枠の描画か塗りつぶしかの選択

例2から例3で、draw(枠の描画)を fill(塗りつぶし)に無条件に変更しましたが、 これを図形ごとに指定するようにしましょう。

ソースプログラム Graph2d2s.java

Graph2d2y.java との差異 (例3の Graph2d2y.java からの変更個所を赤色で表示)

実行例

Graph2d2s-1.gif

【例8】 三角形

三角形も描けるようにしてみましょう。 例5 でいやがっていた RectangularShape の拡張をすることになります。

Graph2d2z-2.gif




左図のように点(x,y) を中心とする幅w、高さhの矩形内に内接する、底辺がy軸に並行な二等辺三角形を を描くことにします。

重なりや包含関係は、この矩形領域で判定することにします。

プログラム Grapn2d2s.java に上向き、下向きの2種類の二等辺三角形を追加します。

プログラム Graph2d2z.java

Graph2d2s.java からの変更点(赤い行番号)

以下の行番号は プログラム Graph2d2z.java の該当個所。

実行例

image/Graph2d2z-1.gif


更新日:2005-12-16 TOPUPPREVNEXT