情報学部 菅沼ホーム Java 目次 基礎技術目次 索引

図形の描画

  1. 描画方法

      描画の話に入る前に,Window における座標系について話をしておきます.Window における座標系は,通常数学などで使用している座標系とは少し異なります.右図に示すように,画面の左上が原点となり,x 座標は右方向が正になりますが,y 座標は下方向が正になるようにとられます.また,単位もピクセル(画素)となります.従って,( 2, 5 ) という座標は,画面の左から 3 番目,上から 6 番目のピクセル(画素)を指すことになります.

      Java には,GUI のための多くのクラス(コンポーネント.GUI を構成するために必要な部品やその入れ物)が準備されています.その一つが,AWT です.AWT の各種コンポーネントは,「ピアモデル」という方法で設計されてきました.ピアpeer )とは,ある作業を行うために自分に協力してくれる仲間ないし相手を言います.AWT の各コンポーネント毎に,それと対をなすプラットホーム固有の部品(ピア,実際の作業を行う)が作成されていました.しかし,ピアをユーザが直接書き直すことができないため,あるコンポーネントの機能を拡張したいような場合は困難が生じます.そこで,ピアを持たないコンポーネント( lightweight component軽量部品)もサポートするようになりました(従来のピアを持つコンポーネントを heavyweight component重量部品と呼ぶ).それらの軽量部品 Swing は「 javax.swing 」,また,AWT は,「 java.awt 」というパッケージにまとめて提供されています.今後,基本的に,Swing を利用して行きます.
      Swing では,AWT と異なり,フレーム等の再描画の時,クライアント領域を背景色で塗りつぶしません.AWT の Frame クラスのクライアント領域は,update() が呼び出されると背景色で塗りつぶして初期化されますが,Swing では update() をオーバーライドし,初期化せずに再描画するようになっています.また,Swing では,高速の描画をサポートするダブルバッファリング機能もデフォルトとしてサポートしています.
      ここでは,Graphics クラスを使用して,上図に示すような簡単な図形を描いてみます.以下に示すのが,Java のソースプログラム Test.java の内容です.
    01	import java.awt.*;
    02	import java.awt.event.*;
    03	import javax.swing.*;
    04	
    05	public class Test {
    06		public static void main (String[] args)
    07		{
    08			Win win = new Win("描画例1");
    09		}
    10	}
    11	
    12	class Win extends JFrame
    13	{
    14		/******************/
    15		/* コンストラクタ */
    16		/******************/
    17		Win(String name)
    18		{
    19						// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    20			super(name);
    21						// Windowの大きさ
    22			setSize(310, 200);   // +40, +70
    23						// ContentPane の取得と MainPanel の追加
    24			MainPanel pn = new MainPanel();   // MainPanel オブジェクトの生成
    25			getContentPane().add(pn);   // MainPanel オブジェクトを ContentPane に追加
    26			pn.setSize(270, 130);
    27						// ウィンドウを表示
    28			setVisible(true);
    29						// イベントアダプタ
    30			addWindowListener(new WinEnd());
    31		}
    32	
    33		/******************************/
    34		/* 上,左,下,右の余白の設定 */
    35		/******************************/
    36		public Insets getInsets()
    37		{
    38			return new Insets(50, 20, 20, 20);
    39		}
    40	
    41		/************/
    42		/* 終了処理 */
    43		/************/
    44		class WinEnd extends WindowAdapter
    45		{
    46			public void windowClosing(WindowEvent e) {
    47				System.exit(0);
    48			}
    49		}
    50	}
    51	
    52	class MainPanel extends JPanel
    53	{
    54		MainPanel()
    55		{
    56			setBackground(new Color(238, 255, 238));   // 背景色の設定
    57		}
    58						// 描画
    59		public void paintComponent(Graphics g)
    60		{
    61			super.paintComponent(g);   // 親クラスの描画
    62								// Graphics2Dの取得
    63			Graphics2D g2 = (Graphics2D)g;
    64								// 線幅が5ピクセルの矩形
    65			g2.setStroke(new BasicStroke(5.0f));
    66			g2.draw(new Rectangle(20, 15, 100, 100));
    67								// 塗りつぶされた円
    68			g.setColor(Color.green);
    69			g.fillOval(30, 25, 80, 80);
    70								// 線幅が5ピクセルの矩形
    71			g.setColor(Color.red);
    72			g2.draw(new Rectangle(150, 15, 100, 100));
    73		}
    74	}
    			
    01 行目~ 03 行目

      「 java.awt 」,「 java.awt.event 」,及び,「 javax.swing 」パッケージにあるすべてのクラスを読み込んでいます.java.awt.Color のように,特定のクラスだけを指定することも可能です.

    05 行目~ 09 行目

      main メソッド( 06 行目~ 08 行目)を含む Test クラスの定義です.main メソッドは,特別なメソッドであり,一つのプログラムに必ず一つだけ存在しなければなりません.この main メソッドでは,Win クラス( 12 行目~ 50 行目で定義)のインスタンス(オブジェクト)を生成しているだけです( 08 行目).

    12 行目~ 50 行目

      Win クラスの定義です.Window を表示するため,JFrame クラスを継承しています.

    17 行目~ 31 行目

      Win メソッドの定義です.一般的に,メソッドは,メソッドを実行するために必要な情報をメソッド名の後ろの括弧内にパラメータリスト(引数)として記述します(この例では,String name が相当).メソッドは,引数として渡された情報などに基づいて何らかの処理を行い,その処理が終了した後,return 文によって,その結果を返します(「 Java とC/C++ 」の 7.1 節参照).

      ただし,Win メソッドはクラス名と同じ名前の特別なメソッドであり,コンストラクタと呼ばれます.クラスのオブジェクトが生成される(この例の場合は,08 行目)と,最初に呼ばれ,初期設定等の作業を行います.なお,コンストラクタにおいては,return 文によって結果を返すことはできません.

    20 行目

      Window のタイトルを引数として渡し,親クラス( JFrame)のコンストラクタを起動しています.なお,super は,親クラスを表すキーワードです.

    22 行目

      Window の大きさを設定しています(幅と高さ).

    24 行目

      描画を行うため,JPanel クラスを継承した MainPanel クラス(クラス名は任意)のインスタンス(オブジェクト)を生成しています.「 MainPanel pn 」の部分は,変数の定義を表しています.Java においても,数学と同じように,定数や様々な値を保持するための変数を使用可能です.ただし,すべての変数には「」があり,その「型」に一致した値だけをその変数に代入(記憶)可能です.「 MainPanel pn 」は,変数 pn が MainPanel クラスのオブジェクト(実際には,オブジェクトのアドレス)を代入(記憶)できる変数であることを宣言しています.この例では,変数 pn は,new 演算子によって生成された MainPanel クラスのオブジェクトによって初期設定初期化)されています(MainPanel クラスのオブジェクトのアドレスが,代入演算子 = 」によって,変数 pn に代入されている).new 演算子は,new の後ろに記述された型が入る領域を確保し,そのアドレスを返す演算子です.

    25 行目

      JFrame クラスのメソッド getContentPane によって,contentPane を取得し,そこに,上で生成した MainPanel クラスのオブジェクトを貼り付けています.JFrame クラスには,JRootPane クラスが唯一の子として格納されます.このクラスのコンテナである contentPane ( JRootPane クラスのフィールドであり,Container クラスのオブジェクトが記憶されている)が,JFrame のすべての子の親になります.そのため,部品の貼り付けやレイアウトの変更( contentPane には,BorderLayout レイアウトマネージャーがデフォルトで設定されている)は,contentPane に対して行ってやる必要があります.もちろん,この行は,以下に示すように 2 行で記述することも可能です.
    	Container cP = getContentPane();
    	cP.add(pn);				
      この例に示すように,自分自身,または,継承した親のクラスのメソッドを使用する場合は,getContentPane のように,そのまま記述すれば良いのですが,他のクラスのメソッドやフィールド(メンバー変数)を利用する際は,どのクラスのメソッドやフィールドなのかを明確にするため,「 getContentPane().add(pn) 」や「 cP.add(pn) 」のように,そのメソッドやフィールドが定義されているクラス(オブジェクト)をピリオド「 . 」によって指定してやる必要があります.

    26 行目

      描画を行う MainPanel の大きさを指定しています.22 行目で指定した Window サイズより小さいのは,MainPanel の上に 50 ピクセル,左右及び下に 20 ピクセルの余白を持たせるためです( 36 行目~ 39 行目参照).

    28 行目

      Window を可視化しています.

    30 行目,44 行目~ 49 行目

      × 印によって Window を閉じるための処理です.イベント処理については,後ほど説明します.

    54 行目~ 57 行目

      MainPanel クラスのコンストラクタであり,背景色を設定しています.

    59 行目~ 73 行目

      JPanel クラスのメソッドである paintComponent をオーバーライドしています.パネルが開始されると,自動的にこのメソッドが呼ばれます.61 行目は常に必要ですので,忘れないでください.

    63 行目

      65 行目のように,描画する線の太さを変更したいため,Graphics オブジェクトから,その機能を持つ Graphics2D クラスのオブジェクトを取得しています.以下,コメントに記述してあるような図形を描いています.

  2. もう一つの例

      以下に示すプログラムでは,下に示すように,角が丸い正方形,楕円,三角形という 3 つの図形を描いています.
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Test {
    	public static void main (String[] args)
    	{
    		Win win = new Win("描画例2");
    	}
    }
    
    class Win extends JFrame
    {
    	/******************/
    	/* コンストラクタ */
    	/******************/
    	Win(String name)
    	{
    					// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    		super(name);
    					// Windowの大きさ
    		setSize(390, 200);   // +40, +70
    					// ContentPane の取得と MainPanel の追加
    		MainPanel pn = new MainPanel();   // MainPanel オブジェクトの生成
    		getContentPane().add(pn);   // MainPanel オブジェクトを ContentPane に追加
    		pn.setSize(350, 130);
    					// ウィンドウを表示
    		setVisible(true);
    					// イベントアダプタ
    		addWindowListener(new WinEnd());
    	}
    
    	/******************************/
    	/* 上,左,下,右の余白の設定 */
    	/******************************/
    	public Insets getInsets()
    	{
    		return new Insets(50, 20, 20, 20);
    	}
    
    	/************/
    	/* 終了処理 */
    	/************/
    	class WinEnd extends WindowAdapter
    	{
    		public void windowClosing(WindowEvent e) {
    			System.exit(0);
    		}
    	}
    }
    
    class MainPanel extends JPanel
    {
    	MainPanel()
    	{
    		setBackground(new Color(238, 255, 238));   // 背景色の設定
    	}
    					// 描画
    	public void paintComponent(Graphics g)
    	{
    		super.paintComponent(g);   // 親クラスの描画
    							// Graphics2Dの取得
    		Graphics2D g2 = (Graphics2D)g;
    							// 線幅が5ピクセルの角が丸い矩形
    		g2.setStroke(new BasicStroke(5.0f));
    		g2.drawRoundRect(20, 15, 100, 100, 50, 50) ;
    							// 塗りつぶされた楕円
    		g.setColor(Color.green);
    		g.fillOval(130, 40, 100, 50);
    							// 三角形
    		g.setColor(Color.red);
    		g2.drawLine(240, 115, 290, 15);
    		g2.drawLine(340, 115, 290, 15);
    		g2.drawLine(240, 115, 340, 115);
    	}
    }
    			

情報学部 菅沼ホーム Java 目次 基礎技術目次 索引