静岡理工科大学 菅沼ホーム Java目次 索引

描画とイベント処理

      1. 描画
      2. イベント処理
      3. 演習問題の解答
      4. ラジオボタン,チェックボックス,ドロップダウンリスト
      5. お絵かき

  1. 描画

      この例では,AWT を利用して,簡単な図形を様々な方法で表示しています.一番左側の図形は Graphics クラスのメソッドを利用して矩形を描いた例です.二番目の図形は,線の太さを変更するために,Graphics2D クラスのメソッドを利用して,同じ図形を描いたものです.三番目の図形では,外部から読み込んだ画像を表示しています.また,最後の図形では,ピクセル値を直接操作して,三番目と同じ図形を生成し,それを表示しています.

    Draw.java( AWT の利用)

    01	import java.awt.*;
    02	import java.awt.image.*;
    03	import java.applet.*;
    04	import java.awt.geom.*;
    05	
    06	public class Draw extends Applet
    07	{
    08		int w = 40, h = 40, size;   // 図形の大きさ
    09		int pixels[];   // 図形
    10		Dimension d;   // 画面の大きさ
    11		MemoryImageSource mis;
    12		Image im1, im2;
    13						// init
    14		public void init() {
    15								// 背景色
    16			setBackground(new Color(238, 255, 238));
    17								// 初期設定
    18			d      = getSize();
    19			size   = w * h;
    20			pixels = new int [size];
    21								// 画像の読み込み
    22			im1 = getImage(getDocumentBase(), "sq.gif");
    23								// ピクセル操作
    24			for (int i1 = 0; i1 < h; i1++) {
    25				for (int i2 = 0; i2 < w; i2++) {
    26					if (i1 < w/2)
    27						pixels[i1*w+i2] = 0xffff0000;
    28					else
    29						pixels[i1*w+i2] = 0xff00ff00;
    30				}
    31			}
    32			mis = new MemoryImageSource(w, h, pixels, 0, w);
    33			im2 = createImage(mis);
    34		}
    35						// 描画
    36		public void paint (Graphics g)
    37		{
    38			int x, y = d.height / 2 - h / 2;
    39								// 描画( Graphics )
    40			x = d.width / 8 - w / 2;
    41			g.setColor(Color.red);   // 描く色
    42			g.drawRect(x, y, w, h/2);   // 四角形の描画
    43			g.setColor(Color.green);   // 描く色
    44			g.drawRect(x, y+h/2, w, h/2);   // 四角形の描画
    45								// 描画( Graphics2D )
    46			x = d.width / 4 + d.width / 8 - w / 2;
    47			Graphics2D g2 = (Graphics2D)g;   // Graphics2D オブジェクトの取得
    48			g2.setStroke(new BasicStroke(5.0f));   // 線の種類と太さ
    49			g2.setColor(Color.red);   // 描く色
    50			g2.draw(new Rectangle2D.Double(x, y, w, h/2));   // 四角形の描画
    51			g2.setColor(Color.green);   // 描く色
    52			g2.draw(new Rectangle2D.Double(x, y+h/2, w, h/2));   // 四角形の描画
    53								// 外部画像
    54			x = d.width / 4 * 2 + d.width / 8 - w / 2;
    55			g.drawImage(im1, x, y, this);
    56								// ピクセル操作
    57			x = d.width / 4 * 3 + d.width / 8 - w / 2;
    58			g.drawImage(im2, x, y, this);
    59		}
    60	}
    			
    04 行目

      Graphics2D クラスのオブジェクトを使用して描画する際に,Shape インタフェースを必要とするため,この記述が必要になる.

    19 行目~ 20 行目

      画像( 40 × 40 ピクセル)の各ピクセル情報を記憶するための配列を定義している.

    22 行目

      画像ファイル( sq.gif )の読み込み

    24 行目~ 31 行目

      画像の上半分が赤に,また,下半分が青になるように,画像データ pixels を設定している.各ピクセルの透明度,赤,緑,青に対する情報が,4 バイト 1 組になり,1 次元配列 pixels に設定される.本来,画像は,画像の高さが h ピクセル,幅が w ピクセルであった場合,h 行 w 列の 2 次元配列としてとらえた方が理解しやすいが,ここでは,それを 1 元配列として表現している.一般に,2 次元配列が連続した領域にとられた場合,2 次元配列の i 行 j 列は,1 次元配列の添え字 (i * w + j) の位置に相当する.

    32 行目

      画像データ pixels から,MemoryImageSource クラスのオブジェクトを生成している.

    33 行目

      MemoryImageSource クラスのオブジェクトを Image クラスのオブジェクトに変換している.

    40 行目~ 44 行目

      Graphics クラスのオブジェクトを利用して,赤,及び,青の矩形を描画している.

    46 行目~ 52 行目

      Graphics2D クラスのオブジェクトを利用して,赤,及び,青の矩形を描画している.BasicStroke クラスは,単純な図形の輪郭線を描画する属性の基本セットを定義する.BasicStroke クラスで定義される描画属性は,Graphics2D オブジェクトによって Shape の輪郭を描画する際,線の太さ,端部の装飾,輪郭線セグメントの接合方法などに利用される.また,Rectangle2D.Double クラスは,Shape インタフェースを継承しており,double 座標で指定される矩形を定義する.

    54 行目~ 58 行目

      外部から読み込んだ画像,及び,ピクセル操作で作成した画像を表示している.

      以下に示すプログラムは,上と同じ描画を,swing を使用して行った例です.JApplet には,JRootPane クラスコンテナが唯一の子として格納されます.JRootPane クラスは,Container クラスの子である JComponent クラスの子である軽量コンテナです.なお,コンテナとは,様々な要素を入れる箱のようなものです.そのため,JRootPane クラスのコンテナが,JApplet のすべての子の親になり,部品の貼り付けやレイアウトの変更は,JRootPane クラスのコンテナに対して行ってやる必要があります.従って,JApplet を継承した場合,JRootPane クラスのコンテナオブジェクトを取得し,その上に描画等を行ってやる必要があります.

      また,先に述べた様に,Swing では,AWT と異なり,JApplet やフレームの再描画の時,クライアント領域を背景色で塗りつぶしません.AWT の Applet や Frame クラスのクライアント領域は,Update() が呼び出されると背景色で塗りつぶして初期化されますが,Swing では Update() をオーバーライドし,初期化せずに再描画するようになっています.また,Swing では,ダブルバッファリング機能もデフォルトとしてサポートしています.一般的に,swing においては,描画する際,paint ではなく,paintComponent をオーバーライドすることになります.

    Draw.java( swing の利用)

    01	import java.awt.*;
    02	import java.awt.image.*;
    03	import javax.swing.*;
    04	import java.awt.geom.*;
    05	
    06	public class Draw extends JApplet
    07	{
    08						// init
    09		public void init()
    10		{
    11			DrawPanel pn = new DrawPanel(this);
    12			getContentPane().add(pn);   
    13		}
    14	}
    15						// DrawPanel
    16	class DrawPanel extends JPanel
    17	{
    18		int w = 40, h = 40, size;   // 図形の大きさ
    19		int pixels[];   // 図形
    20		Dimension d;   // 画面の大きさ
    21		MemoryImageSource mis;
    22		Image im1, im2;
    23	
    24		DrawPanel(Draw dr) {
    25			d = dr.getSize();   // 画面の大きさ
    26								// 背景色
    27			setBackground(new Color(238, 255, 238));
    28								// 初期設定
    29			size   = w * h;
    30			pixels = new int [size];
    31								// 画像の読み込み
    32			im1 = dr.getImage(dr.getDocumentBase(), "sq.gif");
    33								// ピクセル操作
    34			for (int i1 = 0; i1 < h; i1++) {
    35				for (int i2 = 0; i2 < w; i2++) {
    36					if (i1 < w/2)
    37						pixels[i1*w+i2] = 0xffff0000;
    38					else
    39						pixels[i1*w+i2] = 0xff00ff00;
    40				}
    41			}
    42			mis = new MemoryImageSource(w, h, pixels, 0, w);
    43			im2 = createImage(mis);
    44		}
    45						// 描画
    46		public void paintComponent(Graphics g)
    47		{
    48			super.paintComponent(g);   // 親クラスの描画
    49			int x, y = d.height / 2 - h / 2;
    50								// 描画( Graphics )
    51			x = d.width / 8 - w / 2;
    52			g.setColor(Color.red);   // 描く色
    53			g.drawRect(x, y, w, h/2);   // 四角形の描画
    54			g.setColor(Color.green);   // 描く色
    55			g.drawRect(x, y+h/2, w, h/2);   // 四角形の描画
    56								// 描画( Graphics2D )
    57			x = d.width / 4 + d.width / 8 - w / 2;
    58			Graphics2D g2 = (Graphics2D)g;   // Graphics2D オブジェクトの取得
    59			g2.setStroke(new BasicStroke(5.0f));   // 線の種類と太さ
    60			g2.setColor(Color.red);   // 描く色
    61			g2.draw(new Rectangle2D.Double(x, y, w, h/2));   // 四角形の描画
    62			g2.setColor(Color.green);   // 描く色
    63			g2.draw(new Rectangle2D.Double(x, y+h/2, w, h/2));   // 四角形の描画
    64								// 外部画像
    65			x = d.width / 4 * 2 + d.width / 8 - w / 2;
    66			g.drawImage(im1, x, y, this);
    67								// ピクセル操作
    68			x = d.width / 4 * 3 + d.width / 8 - w / 2;
    69			g.drawImage(im2, x, y, this);
    70		}
    71	}
    			
    04 行目

      Graphics2D クラスのオブジェクトを使用して描画する際に,Shape インタフェースを必要とするため,この記述が必要になる.

    11 行目~ 12 行目

      具体的な JRootPane クラスのコンテナオブジェクトは,JRootPane クラスのフィールド contentPane に記憶されている.12 行目では,JRootPane クラスのフィールド contentPane の値( Container クラスのオブジェクト)を,Japplet クラスのメソッドである getContentPane によって取得し,そこに,DrawPanel クラスのオブジェクトを貼り付けている,

    29 行目~ 30 行目

      画像( 40 × 40 ピクセル)の各ピクセル情報を記憶するための配列を定義している.

    32 行目

      画像ファイル( sq.gif )の読み込み

    34 行目~ 41 行目

      画像の上半分が赤に,また,下半分が青になるように,画像データ pixels を設定している.各ピクセルの透明度,赤,緑,青に対する情報が,4 バイト 1 組になり,1 次元配列 pixels に設定される.本来,画像は,画像の高さが h ピクセル,幅が w ピクセルであった場合,h 行 w 列の 2 次元配列としてとらえた方が理解しやすいが,ここでは,それを 1 元配列として表現している.一般に,2 次元配列が連続した領域にとられた場合,2 次元配列の i 行 j 列は,1 次元配列の添え字 (i * w + j) の位置に相当する.

    42 行目

      画像データ pixels から,MemoryImageSource クラスのオブジェクトを生成している.

    43 行目

      MemoryImageSource クラスのオブジェクトを Image クラスのオブジェクトに変換している.

    48 行目

      親クラスのコンストラクタを呼んでいる.paintComponent をオーバーライドするときは必ず必要である.なお,superは,親クラスを表すキーワードである.

    51 行目~ 55 行目

      Graphics クラスのオブジェクトを利用して,赤,及び,青の矩形を描画している.

    57 行目~ 63 行目

      Graphics2D クラスのオブジェクトを利用して,赤,及び,青の矩形を描画している.BasicStroke クラスは,単純な図形の輪郭線を描画する属性の基本セットを定義する.BasicStroke クラスで定義される描画属性は,Graphics2D オブジェクトによって Shape の輪郭を描画する際,線の太さ,端部の装飾,輪郭線セグメントの接合方法などに利用される.また,Rectangle2D.Double クラスは,Shape インタフェースを継承しており,double 座標で指定される矩形を定義する.

    65 行目~ 69 行目

      外部から読み込んだ画像,及び,ピクセル操作で作成した画像を表示している.

  2. イベント処理

      マウスがクリックされた,ボタンが押された,Window が開始された,等のことをイベント(事象)と言います.このようなイベントが発生したとき行う処理をイベント処理といいます.まず,Java において,イベント処理がどのようにして行われているかについて説明します.

      イベントは,イベントの種類毎に,クラスに分類されています. イベントが発生すると,イベントソースは対応するイベントを記述するイベントオブジェクトを生成します.これを,イベントリスナに送出して対応する処理を行うわけですが,そのためには,イベントリスナがそのイベントを「聞く」準備ができていなくてはなりません.その準備を行うのがイベント登録メソッドイベント削除メソッドもあります)です.

      イベントの送出は,リスナのインタフェース(または,イベントアダプタ)に定義されているイベント応答メソッド(ハンドラメソッド)の内1つを呼び出し,引数としてイベントソースが生成したイベントオブジェクトを渡すといった方法で行われます.

      イベントリスナはインタフェースとして提供されています.これは,各イベントの処理がアプリケーションによって異なる場合が多いからです.しかし,インタフェースを実装する際には,インタフェースに定義されているすべてのメソッド(ハンドラメソッド)を実装しない限り,抽象クラスとなり,インスタンスを生成できなくなります.実際にすべてのメソッドを必要とする場合は問題ありませんが,下に示す例(「AWT の利用」,「Swing の利用」)に示すように,一部のメソッドだけを使用したい場合においても,必要としないメソッドまですべて定義しなければならず,余分な作業が必要になります.

    Event.java(インターフェース利用,AWT の利用)

    01	import java.awt.*;
    02	import java.awt.event.*;
    03	import java.applet.*;
    04	
    05	public class Event extends Applet implements MouseListener
    06	{
    07		TextField msg;   // テキストフィールド
    08		Button bt;   // ボタン
    09						// init
    10		public void init() {
    11								// レイアウト,背景色,フォントなど
    12			setLayout(new FlowLayout(FlowLayout.CENTER));
    13			setBackground(new Color(238, 255, 238));
    14			Font f = new Font("TimesRoman", Font.BOLD, 20);
    15			setFont(f);
    16								// ボタン
    17			bt = new Button("送信");
    18			add(bt);
    19			bt.addMouseListener(this);
    20								// テキストフィールド
    21			msg = new TextField("", 10);
    22			add(msg);
    23		}
    24						// ボタンがクリックされたときの処理
    25		public void mouseClicked(MouseEvent e)   // マウスがクリックされたとき
    26		{
    27			if (e.getSource() == bt)
    28				msg.setText("Mouse Click!");
    29		}
    30		public void mouseEntered(MouseEvent e) {}   // マウスがコンポーネントの領域に入ったとき
    31		public void mouseExited(MouseEvent e) {}    // マウスがコンポーネントの領域から出たとき
    32		public void mousePressed(MouseEvent e) {}   // マウスのボタンが押されたとき
    33		public void mouseReleased(MouseEvent e) {}   // マウスのボタンが離されたとき
    34	}
    			
    05 行目

      マウスクリックによるイベント(マウスイベントの一種)を処理するため,MouseListener インタフェースを継承している.

    19 行目

      ボタンに,MouseListener インタフェースを付加している.この結果,ボタンをマウスでクリックすると,MouseListener インタフェースのメソッドである mouseClicked が実行される(テキストフィールドにメッセージが表示される).

    30 行目~ 33 行目

      これらのイベントに対する処理をこのプログラムでは必要としないが,空のメソッドとして定義しておく必要がある.

    Event.java(インターフェース利用,swing の利用)

    01	import java.awt.*;
    02	import java.awt.event.*;
    03	import javax.swing.*;
    04	
    05	public class Event extends JApplet
    06	{
    07						// init
    08		public void init()
    09		{
    10			DrawPanel pn = new DrawPanel();
    11			getContentPane().add(pn);   
    12		}
    13	}
    14						// DrawPanel
    15	class DrawPanel extends JPanel implements MouseListener
    16	{
    17		JTextField msg;   // テキストフィールド
    18		JButton bt;   // ボタン
    19	
    20		DrawPanel() {
    21								// レイアウト,背景色,フォントなど
    22			setLayout(new FlowLayout(FlowLayout.CENTER));
    23			setBackground(new Color(238, 255, 238));
    24			Font f = new Font("TimesRoman", Font.BOLD, 20);
    25								// ボタン
    26			bt = new JButton("送信");
    27			bt.setFont(f);
    28			add(bt);
    29			bt.addMouseListener(this);
    30								// テキストフィールド
    31			msg = new JTextField("", 10);
    32			msg.setFont(f);
    33			add(msg);
    34		}
    35						// ボタンがクリックされたときの処理
    36		public void mouseClicked(MouseEvent e)   // マウスがクリックされたとき
    37		{
    38			if (e.getSource() == bt)
    39				msg.setText("Mouse Click!");
    40		}
    41		public void mouseEntered(MouseEvent e) {}   // マウスがコンポーネントの領域に入ったとき
    42		public void mouseExited(MouseEvent e) {}    // マウスがコンポーネントの領域から出たとき
    43		public void mousePressed(MouseEvent e) {}   // マウスのボタンが押されたとき
    44		public void mouseReleased(MouseEvent e) {}   // マウスのボタンが離されたとき
    45	}
    			
    15 行目

      マウスクリックによるイベント(マウスイベントの一種)を処理するため,MouseListener インタフェースを継承している.

    29 行目

      ボタンに,MouseListener インタフェースを付加している.この結果,ボタンをマウスでクリックすると,MouseListener インタフェースのメソッドである mouseClicked が実行される(テキストフィールドにメッセージが表示される).

    41 行目~ 44 行目

      これらのイベントに対する処理をこのプログラムでは必要としないが,空のメソッドとして定義しておく必要がある.

      イベントアダプタクラスを利用すれば,この煩わしさを避けることが可能です.イベントアダプタは,すべてのメソッドに対する標準的処理を実装しているため,このクラスのサブクラスとしてクラスを定義すれば,必要なメソッドの実装だけで済むことになります.しかし,Java においては多重継承が許されませので,内部クラス(クラス内に定義されたクラス,この例ではクラス Mouse )を定義してイベント処理を行うのが通常の方法です.次の例(「AWT の利用」,「Swing の利用」)は,上と同じ例に対しイベントアダプタ( MouseAdapter クラス)を使用して実行しています.

    Event.java(イベントアダプタ利用,AWT の利用)

    import java.awt.*;
    import java.awt.event.*;
    import java.applet.*;
    
    public class Event extends Applet
    {
    	TextField msg;   // テキストフィールド
    	Button bt;   // ボタン
    					// init
    	public void init() {
    							// レイアウト,背景色,フォントなど
    		setLayout(new FlowLayout(FlowLayout.CENTER));
    		setBackground(new Color(238, 255, 238));
    		Font f = new Font("TimesRoman", Font.BOLD, 20);
    		setFont(f);
    							// ボタン
    		bt = new Button("送信");
    		add(bt);
    		bt.addMouseListener(new Mouse());
    							// テキストフィールド
    		msg = new TextField("", 10);
    		add(msg);
    	}
    					// ボタンがクリックされたときの処理
    	class Mouse extends MouseAdapter
    	{
    		public void mouseClicked(MouseEvent e)   // マウスがクリックされたとき
    		{
    			if (e.getSource() == bt)
    				msg.setText("Mouse Click!");
    		}
    	}
    }
    			

    Event.java(イベントアダプタ利用,swing の利用)

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Event extends JApplet
    {
    					// init
    	public void init()
    	{
    		DrawPanel pn = new DrawPanel();
    		getContentPane().add(pn);   
    	}
    }
    					// DrawPanel
    class DrawPanel extends JPanel
    {
    	JTextField msg;   // テキストフィールド
    	JButton bt;   // ボタン
    
    	DrawPanel() {
    							// レイアウト,背景色,フォントなど
    		setLayout(new FlowLayout(FlowLayout.CENTER));
    		setBackground(new Color(238, 255, 238));
    		Font f = new Font("TimesRoman", Font.BOLD, 20);
    							// ボタン
    		bt = new JButton("送信");
    		bt.setFont(f);
    		add(bt);
    		bt.addMouseListener(new Mouse());
    							// テキストフィールド
    		msg = new JTextField("", 10);
    		msg.setFont(f);
    		add(msg);
    	}
    					// ボタンがクリックされたときの処理
    	class Mouse extends MouseAdapter
    	{
    		public void mouseClicked(MouseEvent e)   // マウスがクリックされたとき
    		{
    			if (e.getSource() == bt)
    				msg.setText("Mouse Click!");
    		}
    	}
    }
    			

  3. 演習問題の解答

      以下,描画やイベント処理に対する例をいくつか挙げていきます.まず最初に示す例(「AWT の利用」,「Swing の利用」)は,JavaScript に対する説明で述べた JavaScript だけで記述した演習問題の解答(正誤の判断)と同じ機能を持ったページを Java で記述したものです.以下に,Java プログラムのソースを示します.表示されたページのソースを見てもらえば明らかなように,HTML ファイルでは,単に,アプレットを埋め込んでいるだけです.

    AWT を利用した場合

    001	import java.applet.*;
    002	import java.util.*;
    003	import java.awt.*;
    004	import java.awt.event.*;
    005	public class Test extends Applet implements ActionListener
    006	{
    007		int a = 3, b = 4, c;
    008		TextField ans, name;
    009		Button bt;
    010		Label lb1, lb2, shiki;
    011		Panel pn1, pn2;
    012		Random rn;
    013	
    014		/************/
    015		/* 初期設定 */
    016		/************/
    017		public void init()
    018		{
    019						// レイアウト,背景色,フォントなど
    020			setLayout(new BorderLayout(5, 10));
    021			setBackground(new Color(225, 255, 225));
    022			Font f = new Font("TimesRoman", Font.BOLD, 20);
    023			setFont(f);
    024			rn = new Random();
    025						// 上のパネル
    026			pn1 = new Panel();
    027			pn1.setLayout(new FlowLayout(FlowLayout.CENTER));
    028			add(pn1, BorderLayout.NORTH);
    029			lb2 = new Label("次の問題の答えは?");
    030			pn1.add(lb2);
    031						// 中央のパネル
    032			pn2 = new Panel();
    033			add(pn2, BorderLayout.CENTER);
    034			shiki = new Label("3 + 4 = ");
    035			pn2.add(shiki);
    036			ans = new TextField("", 3);
    037			pn2.add(ans);
    038						// 下のパネル
    039			Panel pn3 = new Panel();
    040			add(pn3, BorderLayout.SOUTH);
    041			pn3.add(new Label("名前:"));
    042			name = new TextField("", 10);
    043			pn3.add(name);
    044			bt = new Button("送信");
    045			bt.addActionListener(this);
    046			pn3.add(bt);
    047		}
    048	
    049		/******************************/
    050		/* 上,左,下,右の余白の設定 */
    051		/******************************/
    052		public Insets getInsets()
    053		{
    054			return new Insets(10, 10, 10, 10);
    055		}
    056		/******************************/
    057		/* ボタンが押されたときの処理 */
    058		/******************************/
    059		public void actionPerformed(ActionEvent e)
    060		{
    061			int sw = 0;
    062			Dialogbox db = null;
    063			if (ans.getText().length() <= 0) {
    064				db = new Dialogbox(" 答えを入力してください");
    065				sw = 1;
    066			}
    067			else if (name.getText().length() <= 0) {
    068				db = new Dialogbox(" 名前を入力してください");
    069				sw = 1;
    070			}
    071			if (sw > 0) {
    072				db.setSize(300,130);
    073				Toolkit tool = getToolkit();
    074				Dimension d = tool.getScreenSize();
    075				db.setLocation(d.width / 2 - 150, d.height / 2 - 65);
    076				db.setVisible(true);
    077			}
    078			else {
    079				c = Integer.parseInt(ans.getText());
    080				if (a + b == c) {
    081					lb1   = new Label(name.getText() + "さん,正解です");
    082					lb2   = new Label("続いて,次の問題の答えは?");
    083					a     = (int)(100.0 * rn.nextDouble());
    084					b     = (int)(100.0 * rn.nextDouble());
    085					shiki = new Label(Integer.toString(a) + " + " + Integer.toString(b) + " = ");
    086				}
    087				else {
    088					lb1 = new Label(name.getText() + "さん,間違っています");
    089					lb2 = new Label("もう一度計算してみて下さい");
    090				}
    091				remove(pn1);
    092				remove(pn2);
    093				pn1 = new Panel();
    094				pn1.setLayout(new GridLayout(2, 1, 10, 10));
    095				add(pn1, BorderLayout.NORTH);
    096				Panel pn11 = new Panel();
    097				pn11.setLayout(new FlowLayout(FlowLayout.CENTER));
    098				pn1.add(pn11);
    099				pn11.add(lb1);
    100				Panel pn12 = new Panel();
    101				pn12.setLayout(new FlowLayout(FlowLayout.CENTER));
    102				pn1.add(pn12);
    103				pn12.add(lb2);
    104				pn2 = new Panel();
    105				add(pn2, BorderLayout.CENTER);
    106				pn2.add(shiki);
    107				ans = new TextField("", 3);
    108				pn2.add(ans);
    109				getParent().validate();
    110			}
    111		}
    112	}
    113	
    114	/*******************/
    115	/* Dialogboxクラス */
    116	/*******************/
    117	class Dialogbox extends Frame {
    118		Dialogbox(String message)
    119		{
    120			super("Error");
    121			setFont(new Font("TimesRoman", Font.BOLD, 20));
    122			add(new Label(message));
    123			addWindowListener(new WinEnd());
    124		}
    125		class WinEnd extends WindowAdapter
    126		{
    127			public void windowClosing(WindowEvent e) {
    128				setVisible(false);
    129			}
    130		}
    131	}
    			
    005 行目

      Applet クラスを継承すると共に,「送信」ボタンがクリックされたときの処理を行うため,インタフェース ActionListener を継承

    020 行目

      レイアウトマネージャ( BorderLayout )の設定

    021 行目

      背景色の設定

    022 行目~ 023 行目

      Font クラスのオブジェクトを生成し設定している.

    024 行目

      Random クラスのオブジェクトの生成(新しい乱数の初期化)

    026 行目~ 028 行目

      BorderLayout の上部( BorderLayout.NORTH )に Panel クラスのオブジェクト pn1 を追加し,そのレイアウトマネージャとして FlowLayout を設定している.

    029 行目~ 030 行目

      Panel クラスのオブジェクト pn1 に,「次の問題の答えは?」というメッセージを表示するため,Label クラスのオブジェクトを追加している.

    032 行目~ 037 行目

      BorderLayout の中央( BorderLayout.CENTER )に Panel クラスのオブジェクト pn2 を追加し,そこに,問題を表示するための Label クラスのオブジェクトと,答を入力するため,TextField クラスのオブジェクトを追加している.

    039 行目~ 046 行目

      BorderLayout の下部( BorderLayout.SOUTH )に Panel クラスのオブジェクト pn3 を追加し,そこに,名前を入力するための TextField クラスのオブジェクトと,答を送信するため,Button クラスのオブジェクトを追加している.なお,Button クラスのオブジェクトには,ボタンがクリックされたときの処理を行うため,ActionListener を追加している.

    052 行目~ 055 行目

      アプレットと実際に描画される領域間の余白を設定している.

    059 行目~ 111 行目

      「送信」ボタンがクリックされたときの処理である.
    • 063 行目~ 066 行目: 答えが入力されていない場合は,「答えを入力してください」というメッセージを出力する Dialogbox クラス(後述)のオブジェクトを生成している.
    • 067 行目~ 070 行目: 上と同様,名前が入力されていない場合の処理である.
    • 071 行目~ 077 行目: 答え,または,名前が入力されていない場合の処理であり,スクリーンの指定された位置に,Dialogbox クラスのオブジェクト(ダイアログボックス)を表示する.
    • 079 行目: 答え領域に入力されたデータを Integer クラスのスタティックメソッド parseInt を利用して整数に変換している.
    • 081 行目~ 085 行目: 答えが正しかった場合の処理であり,メッセージと次の問題を Label クラスのオブジェクト lb1,lb2,及び,shiki に設定している.
    • 088 行目~ 089 行目: 答えが間違っていた場合の処理であり,メッセージを Label クラスのオブジェクト lb1,及び,lb2 に設定している.

    091 行目~ 109 行目

      Panel クラスのオブジェクト pn1,及び,pn2 を取り除き( 091 行目~ 092 行目),上で設定した Label クラスのオブジェクトに従って,Panel クラスのオブジェクト pn1,及び,pn2 を再設定している.なお,validate は,コンテナが格納しているコンポーネントが追加または変更されたあとで,コンテナがそのサブコンポーネントをもう一度配置できるようにするためのメソッドである.

    117 行目~ 131 行目

      Dialogbox クラスの定義である.
    • 117 行目: 新しい Window を生成するため,Frame クラスを継承している.
    • 120 行目: Window のタイトルとなる文字列を引数として,親クラス( Frame クラス)のコンストラクタを呼び出している .
    • 123 行目: Window の「×」ボタンをクリックしたとき,Window を終了させるために WindowListener を追加している.
    • 125 行目~ 130 行目: Window の「×」ボタンがクリックされたときの処理であり,Window を終了させている.

    Swing を利用した場合

    001	import javax.swing.*;
    002	import java.util.*;
    003	import java.awt.*;
    004	import java.awt.event.*;
    005	public class Test extends JApplet implements ActionListener
    006	{
    007		int a = 3, b = 4, c;
    008		JTextField ans, name;
    009		JButton bt;
    010		JLabel lb1, lb2, shiki;
    011		JPanel pn1, pn2;
    012		Random rn;
    013		Font f;
    014		Container cp;
    015	
    016		/************/
    017		/* 初期設定 */
    018		/************/
    019		public void init()
    020		{
    021						// レイアウト,背景色,フォントなど
    022			cp = getContentPane();
    023			cp.setBackground(new Color(225, 255, 225));
    024			f = new Font("TimesRoman", Font.BOLD, 20);
    025			rn = new Random();
    026						// 上のパネル
    027			pn1 = new JPanel();
    028			pn1.setBackground(new Color(225, 255, 225));
    029			pn1.setLayout(new FlowLayout(FlowLayout.CENTER));
    030			cp.add(pn1, BorderLayout.NORTH);
    031			lb2 = new JLabel("次の問題の答えは?");
    032			lb2.setFont(f);
    033			pn1.add(lb2);
    034						// 中央のパネル
    035			pn2 = new JPanel();
    036			pn2.setBackground(new Color(225, 255, 225));
    037			cp.add(pn2, BorderLayout.CENTER);
    038			shiki = new JLabel("3 + 4 = ");
    039			shiki.setFont(f);
    040			pn2.add(shiki);
    041			ans = new JTextField("", 3);
    042			ans.setFont(f);
    043			ans.setHorizontalAlignment(JTextField.RIGHT);
    044			pn2.add(ans);
    045						// 下のパネル
    046			JPanel pn3 = new JPanel();
    047			pn3.setBackground(new Color(225, 255, 225));
    048			add(pn3, BorderLayout.SOUTH);
    049			JLabel lb3 = new JLabel("名前:");
    050			lb3.setFont(f);
    051			pn3.add(lb3);
    052			name = new JTextField("", 10);
    053			name.setFont(f);
    054			pn3.add(name);
    055			bt = new JButton("送信");
    056			bt.setFont(f);
    057			bt.addActionListener(this);
    058			pn3.add(bt);
    059		}
    060	
    061		/******************************/
    062		/* 上,左,下,右の余白の設定 */
    063		/******************************/
    064		public Insets getInsets()
    065		{
    066			return new Insets(10, 10, 10, 10);
    067		}
    068		/******************************/
    069		/* ボタンが押されたときの処理 */
    070		/******************************/
    071		public void actionPerformed(ActionEvent e)
    072		{
    073			int sw = 0;
    074			Dialogbox db = null;
    075			if (ans.getText().length() <= 0) {
    076				db = new Dialogbox(" 答えを入力してください");
    077				sw = 1;
    078			}
    079			else if (name.getText().length() <= 0) {
    080				db = new Dialogbox(" 名前を入力してください");
    081				sw = 1;
    082			}
    083			if (sw > 0) {
    084				db.setSize(300,130);
    085				Toolkit tool = getToolkit();
    086				Dimension d = tool.getScreenSize();
    087				db.setLocation(d.width / 2 - 150, d.height / 2 - 65);
    088				db.setVisible(true);
    089			}
    090			else {
    091				c = Integer.parseInt(ans.getText());
    092				if (a + b == c) {
    093					lb1   = new JLabel(name.getText() + "さん,正解です");
    094					lb2   = new JLabel("続いて,次の問題の答えは?");
    095					a     = (int)(100.0 * rn.nextDouble());
    096					b     = (int)(100.0 * rn.nextDouble());
    097					shiki = new JLabel(Integer.toString(a) + " + " + Integer.toString(b) + " = ");
    098					lb1.setFont(f);
    099					lb2.setFont(f);
    100					shiki.setFont(f);
    101				}
    102				else {
    103					lb1 = new JLabel(name.getText() + "さん,間違っています");
    104					lb2 = new JLabel("もう一度計算してみて下さい");
    105					lb1.setFont(f);
    106					lb2.setFont(f);
    107				}
    108				remove(pn1);
    109				remove(pn2);
    110				pn1 = new JPanel();
    111				pn1.setBackground(new Color(225, 255, 225));
    112				pn1.setLayout(new GridLayout(2, 1, 10, 10));
    113				cp.add(pn1, BorderLayout.NORTH);
    114				JPanel pn11 = new JPanel();
    115				pn11.setBackground(new Color(225, 255, 225));
    116				pn11.setLayout(new FlowLayout(FlowLayout.CENTER));
    117				pn1.add(pn11);
    118				pn11.add(lb1);
    119				JPanel pn12 = new JPanel();
    120				pn12.setBackground(new Color(225, 255, 225));
    121				pn12.setLayout(new FlowLayout(FlowLayout.CENTER));
    122				pn1.add(pn12);
    123				pn12.add(lb2);
    124				pn2 = new JPanel();
    125				pn2.setBackground(new Color(225, 255, 225));
    126				cp.add(pn2, BorderLayout.CENTER);
    127				pn2.add(shiki);
    128				ans = new JTextField("", 3);
    129				ans.setFont(f);
    130				ans.setHorizontalAlignment(JTextField.RIGHT);
    131				pn2.add(ans);
    132				getParent().validate();
    133			}
    134		}
    135	}
    136	
    137	/*******************/
    138	/* Dialogboxクラス */
    139	/*******************/
    140	class Dialogbox extends JFrame {
    141		Dialogbox(String message)
    142		{
    143			super("Error");
    144			Container cp = getContentPane();
    145			cp.setBackground(Color.white);
    146			JLabel lb = new JLabel(message);
    147			lb.setFont(new Font("TimesRoman", Font.BOLD, 20));
    148			cp.add(lb);
    149			addWindowListener(new WinEnd());
    150		}
    151		class WinEnd extends WindowAdapter
    152		{
    153			public void windowClosing(WindowEvent e) {
    154				setVisible(false);
    155			}
    156		}
    157	}
    			
    005 行目

      JApplet クラスを継承すると共に,「送信」ボタンがクリックされたときの処理を行うため,インタフェース ActionListener を継承

    022 行目

      JRootPane は,Container クラスの子である JComponent クラスの子である軽量コンテナである.なお,コンテナとは,様々な要素を入れる箱のようなものである.JApplet には,JRootPane のコンテナが唯一の子として格納される.そのため,JRootPane クラスのコンテナが,JApplet のすべての子の親になり,部品の貼り付けやレイアウトの変更は,JRootPane クラスのコンテナに対して行ってやる必要がある.具体的な JRootPane クラスのコンテナオブジェクトは,JRootPane クラスのフィールド contentPane に記憶されている.022 行目では,JRootPane クラスのフィールド contentPane の値( Container クラスのオブジェクト)を,Japplet クラスのメソッドである getContentPane によって取得している,

    023 行目

      背景色の設定

    024 行目

      Font クラスのオブジェクトの生成

    025 行目

      Random クラスのオブジェクトの生成(新しい乱数の初期化)

    027 行目~ 030 行目

      BorderLayout の上部( BorderLayout.NORTH )に JPanel クラスのオブジェクト pn1 を追加し,その背景色及びレイアウトマネージャ( FlowLayout )を設定している.

    031 行目~ 033 行目

      「次の問題の答えは?」というメッセージを表示するため,JLabel クラスのオブジェクトを生成し,そのフォントを設定した後,JPanel クラスのオブジェクト pn1 に追加している.

    035 行目~ 044 行目

      BorderLayout の中央( BorderLayout.CENTER )に JPanel クラスのオブジェクト pn2 を追加し,そこに,問題を表示するための JLabel クラスのオブジェクトと,答を入力するため,JTextField クラスのオブジェクトを追加している.なお,043 行目は,文字列を右寄せで表示するための設定である.

    046 行目~ 058 行目

      BorderLayout の下部( BorderLayout.SOUTH )に JPanel クラスのオブジェクト pn3 を追加し,そこに,名前を入力するための JTextField クラスのオブジェクトと,答を送信するため,JButton クラスのオブジェクトを追加している.なお,JButton クラスのオブジェクトには,ボタンがクリックされたときの処理を行うため,ActionListener を追加している.

    064 行目~ 067 行目

      アプレットと実際に描画される領域間の余白を設定している.

    071 行目~ 134 行目

      「送信」ボタンがクリックされたときの処理である.
    • 075 行目~ 078 行目: 答えが入力されていない場合は,「答えを入力してください」というメッセージを出力する Dialogbox クラス(後述)のオブジェクトを生成している.
    • 079 行目~ 082 行目: 上と同様,名前が入力されていない場合の処理である.
    • 083 行目~ 089 行目: 答え,または,名前が入力されていない場合の処理であり,スクリーンの指定された位置に,Dialogbox クラスのオブジェクト(ダイアログボックス)を表示する.
    • 091 行目: 答え領域に入力されたデータを Integer クラスのスタティックメソッド parseInt を利用して整数に変換している.
    • 093 行目~ 100 行目: 答えが正しかった場合の処理であり,メッセージと次の問題を JLabel クラスのオブジェクト lb1,lb2,及び,shiki に設定している.
    • 103 行目~ 106 行目: 答えが間違っていた場合の処理であり,メッセージを JLabel クラスのオブジェクト lb1,及び,lb2 に設定している.

    108 行目~ 132 行目

      JPanel クラスのオブジェクト pn1,及び,pn2 を取り除き( 108 行目~ 109 行目),上で設定した JLabel クラスのオブジェクトに従って,JPanel クラスのオブジェクト pn1,及び,pn2 を再設定している.なお,validate は,コンテナが格納しているコンポーネントが追加または変更されたあとで,コンテナがそのサブコンポーネントをもう一度配置できるようにするためのメソッドである.

    140 行目~ 157 行目

      Dialogbox クラスの定義である.
    • 140 行目: 新しい Window を生成するため,JFrame クラスを継承している.
    • 143 行目: Window のタイトルとなる文字列を引数として,親クラス( JFrame クラス)のコンストラクタを呼び出している .
    • 149 行目: Window の「×」ボタンをクリックしたとき,Window を終了させるために WindowListener を追加している.
    • 151 行目~ 156 行目: Window の「×」ボタンがクリックされたときの処理であり,Window を終了させている.

      Java アプレットの場合,クライアント側で実行されるため,サーバ側のファイルを読む場合は Java だけで記述できますが,サーバ側にデータを記録したいような場合は,フォームにおける CGI に相当するプログラムが必要になります.その方法を示すために,以下に示すアプレットでは,上で述べた演習問題の解答の例に対して,正誤のチェックだけをサーバで行うように修正してあります.

      また,このアプレット(「AWT の利用」,「Swing の利用」)では,正誤の判定結果をテキストエリアに表示するようにしています.このように,Java アプレットの場合は,新しいページを開くことなく,同じページ内で何回もサーバとの交信を繰り返すことが可能です.また,フォームの場合とは異なり,サーバ側に任意のデータを送信できます.以下に示すのは,Java のソースプログラム( Problem.java )です.

    AWT を利用した場合

    001	import java.applet.*;
    002	import java.util.*;
    003	import java.awt.*;
    004	import java.awt.event.*;
    005	import java.net.*;
    006	import java.io.*;
    007	public class Problem extends Applet implements ActionListener
    008	{
    009		int a = 3, b = 4, c;
    010		TextField ans, name;
    011		TextArea ta;
    012		Button bt;
    013		Label shiki;
    014		Random rn;
    015		URL url;
    016	
    017		/************/
    018		/* 初期設定 */
    019		/************/
    020		public void init()
    021		{
    022						// CGI ファイルの設定
    023			try {
    024				url = new URL(getCodeBase(), "check.php");
    025			}
    026			catch (MalformedURLException e) {
    027				ta.setForeground(Color.red);
    028				ta.setText("Error: " + e.getMessage());
    029			}
    030						// レイアウト,背景色,フォントなど
    031			setLayout(new BorderLayout(5, 10));
    032			setBackground(new Color(225, 255, 225));
    033			setFont(new Font("TimesRoman", Font.BOLD, 20));
    034			rn = new Random();
    035						// 上のパネル
    036			Panel pn1 = new Panel();
    037			pn1.setLayout(new FlowLayout(FlowLayout.CENTER));
    038			add(pn1, BorderLayout.NORTH);
    039			pn1.add(new Label("次の問題の答えは?"));
    040						// 中央のパネル
    041			Panel pn2 = new Panel();
    042			pn2.setLayout(new GridLayout(2, 1, 10, 10));
    043			add(pn2, BorderLayout.CENTER);
    044			Panel pn21 = new Panel();
    045			pn21.setLayout(new FlowLayout(FlowLayout.CENTER));
    046			pn2.add(pn21);
    047			shiki = new Label("    3 + 4 = ");
    048			pn21.add(shiki);
    049			ans = new TextField("", 3);
    050			pn21.add(ans);
    051			Panel pn22 = new Panel();
    052			pn22.setLayout(new FlowLayout(FlowLayout.CENTER));
    053			pn2.add(pn22);
    054			pn22.add(new Label("名前:"));
    055			name = new TextField("", 10);
    056			pn22.add(name);
    057			bt = new Button("送信");
    058			bt.addActionListener(this);
    059			pn22.add(bt);
    060						// 下のパネル
    061			Panel pn3 = new Panel();
    062			add(pn3, BorderLayout.SOUTH);
    063			ta = new TextArea(2, 30);
    064			pn3.add(ta);
    065		}
    066	
    067		/******************************/
    068		/* 上,左,下,右の余白の設定 */
    069		/******************************/
    070		public Insets getInsets()
    071		{
    072			return new Insets(10, 10, 10, 10);
    073		}
    074	
    075		/******************************/
    076		/* ボタンが押されたときの処理 */
    077		/******************************/
    078		public void actionPerformed(ActionEvent e)
    079		{
    080			int sw = 0;
    081			Dialogbox db = null;
    082			URLConnection c_URL;
    083			OutputStream o_stm = null;
    084			PrintStream out = null;
    085			InputStream i_stm = null;
    086			BufferedReader in = null;
    087			String str;
    088			if (ans.getText().length() <= 0) {
    089				db = new Dialogbox(" 答えを入力してください");
    090				sw = 1;
    091			}
    092			else if (name.getText().length() <= 0) {
    093				db = new Dialogbox(" 名前を入力してください");
    094				sw = 1;
    095			}
    096			if (sw > 0) {
    097				db.setSize(300,130);
    098				Toolkit tool = getToolkit();
    099				Dimension d = tool.getScreenSize();
    100				db.setLocation(d.width / 2 - 150, d.height / 2 - 65);
    101				db.setVisible(true);
    102			}
    103			else {
    104				try {
    105					c_URL = url.openConnection();
    106					c_URL.setDoInput(true);
    107					c_URL.setDoOutput(true);
    108					c_URL.setUseCaches(false);
    109					c_URL.connect();
    110						// 出力
    111					o_stm = c_URL.getOutputStream();
    112					out   = new PrintStream(o_stm);
    113					c     = Integer.parseInt(ans.getText());
    114					out.println("ans=" + a + "," + b + "," + c);
    115					out.close();
    116						// 入力
    117					i_stm = c_URL.getInputStream();
    118					in    = new BufferedReader(new InputStreamReader(i_stm));
    119					str   = in.readLine();
    120					in.close();
    121					if (Integer.parseInt(str) > 0) {
    122						ta.setForeground(Color.black);
    123						ta.setText(" " + name.getText() + "さん,正解です\n");
    124						ta.append(" 続いて,次の問題の答えは?");
    125						a = (int)(100.0 * rn.nextDouble());
    126						b = (int)(100.0 * rn.nextDouble());
    127						ans.setText("");
    128						shiki.setText(Integer.toString(a) + " + " + Integer.toString(b) + " = ");
    129					}
    130					else {
    131						ta.setForeground(Color.red);
    132						ta.setText(" " + name.getText() + "さん,間違っています\n");
    133						ta.append(" もう一度計算してみて下さい");
    134					}
    135				}
    136				catch (IOException e1) {
    137					ta.setForeground(Color.red);
    138					ta.setText("IO Error: " + e1.getMessage());
    139				}
    140			}
    141		}
    142	}
    143	
    144	/*******************/
    145	/* Dialogboxクラス */
    146	/*******************/
    147	class Dialogbox extends Frame {
    148		Dialogbox(String message)
    149		{
    150			super("Error");
    151			setFont(new Font("TimesRoman", Font.BOLD, 20));
    152			add(new Label(message));
    153			addWindowListener(new WinEnd());
    154		}
    155		class WinEnd extends WindowAdapter
    156		{
    157			public void windowClosing(WindowEvent e) {
    158				setVisible(false);
    159			}
    160		}
    161	}
    			
    023 行目~ 029 行目

      CGI プログラム( check.php,データを送信するプログラム)に基づき,URL クラスのオブジェクトを生成しています.

    104 行目~ 139 行目

      「送信」ボタンがクリックされ,答えや名前に対する入力漏れがなかった場合に対する処理である.
    • 105 行目~ 109 行目: 023 行目~ 029 行目において生成されたオブジェクトに基づき,URLConnection クラスのオブジェクトを生成し,接続している.
    • 111 行目~ 115 行目: 問題と答えを含んだ文字列を出力ストリームに出力した後,出力ストリームを閉じている.例えば,「 3 + 4 = 7 」のような問題であれば,送信される文字列は,「 ans=3,4,7 」となる.
    • 117 行目~ 120 行目: CGI プログラムから送られてきた文字列を読み込み,変数 str に保存した後,入力ストリームを閉じている.
    • 121 行目~ 129 行目: 答えが正しかった場合の処理であり,メッセージと次の問題をテキストエリアに出力している.なお,CGI プログラムからは,答えが正しかった場合は "1" が,間違っていた場合は "0" が送られてくる.
    • 130 行目~ 134 行目: 答えが間違っていた場合の処理であり,メッセージを テキストエリアに出力している.

    Swing を利用した場合

    001	import javax.swing.*;
    002	import java.util.*;
    003	import java.awt.*;
    004	import java.awt.event.*;
    005	import java.net.*;
    006	import java.io.*;
    007	public class Problem extends JApplet implements ActionListener
    008	{
    009		int a = 3, b = 4, c;
    010		JTextField ans, name;
    011		JTextArea ta;
    012		JButton bt;
    013		JLabel shiki;
    014		Random rn;
    015		URL url;
    016	
    017		/************/
    018		/* 初期設定 */
    019		/************/
    020		public void init()
    021		{
    022						// CGI ファイルの設定
    023			try {
    024				url = new URL(getCodeBase(), "check.php");
    025			}
    026			catch (MalformedURLException e) {
    027				ta.setForeground(Color.red);
    028				ta.setText("Error: " + e.getMessage());
    029			}
    030						// レイアウト,背景色,フォントなど
    031			Container cp = getContentPane();
    032			cp.setBackground(new Color(225, 255, 225));
    033			Font f = new Font("TimesRoman", Font.BOLD, 20);
    034			rn = new Random();
    035						// 上のパネル
    036			JPanel pn1 = new JPanel();
    037			pn1.setLayout(new FlowLayout(FlowLayout.CENTER));
    038			pn1.setBackground(new Color(225, 255, 225));
    039			cp.add(pn1, BorderLayout.NORTH);
    040			JLabel lb1 = new JLabel("次の問題の答えは?");
    041			lb1.setFont(f);
    042			pn1.add(lb1);
    043						// 中央のパネル
    044			JPanel pn2 = new JPanel();
    045			pn2.setLayout(new GridLayout(2, 1, 10, 10));
    046			pn2.setBackground(new Color(225, 255, 225));
    047			cp.add(pn2, BorderLayout.CENTER);
    048			JPanel pn21 = new JPanel();
    049			pn21.setLayout(new FlowLayout(FlowLayout.CENTER));
    050			pn21.setBackground(new Color(225, 255, 225));
    051			pn2.add(pn21);
    052			shiki = new JLabel("    3 + 4 = ");
    053			shiki.setFont(f);
    054			pn21.add(shiki);
    055			ans = new JTextField("", 3);
    056			ans.setBackground(Color.white);
    057			ans.setFont(f);
    058			ans.setHorizontalAlignment(JTextField.RIGHT);
    059			pn21.add(ans);
    060			JPanel pn22 = new JPanel();
    061			pn22.setLayout(new FlowLayout(FlowLayout.CENTER));
    062			pn22.setBackground(new Color(225, 255, 225));
    063			pn2.add(pn22);
    064			JLabel lb2 = new JLabel("名前:");
    065			lb2.setFont(f);
    066			pn22.add(lb2);
    067			name = new JTextField("", 10);
    068			name.setBackground(Color.white);
    069			name.setFont(f);
    070			pn22.add(name);
    071			bt = new JButton("送信");
    072			bt.setFont(f);
    073			bt.addActionListener(this);
    074			pn22.add(bt);
    075						// 下のパネル
    076			JPanel pn3 = new JPanel();
    077			pn3.setBackground(new Color(225, 255, 225));
    078			cp.add(pn3, BorderLayout.SOUTH);
    079			ta = new JTextArea(2, 20);
    080			ta.setFont(f);
    081			ta.setBackground(Color.white);
    082			JScrollPane sp = new JScrollPane(ta);
    083			pn3.add(sp);
    084		}
    085	
    086		/******************************/
    087		/* 上,左,下,右の余白の設定 */
    088		/******************************/
    089		public Insets getInsets()
    090		{
    091			return new Insets(10, 10, 10, 10);
    092		}
    093	
    094		/******************************/
    095		/* ボタンが押されたときの処理 */
    096		/******************************/
    097		public void actionPerformed(ActionEvent e)
    098		{
    099			int sw = 0;
    100			Dialogbox db = null;
    101			URLConnection c_URL;
    102			OutputStream o_stm = null;
    103			PrintStream out = null;
    104			InputStream i_stm = null;
    105			BufferedReader in = null;
    106			String str;
    107			if (ans.getText().length() <= 0) {
    108				db = new Dialogbox(" 答えを入力してください");
    109				sw = 1;
    110			}
    111			else if (name.getText().length() <= 0) {
    112				db = new Dialogbox(" 名前を入力してください");
    113				sw = 1;
    114			}
    115			if (sw > 0) {
    116				db.setSize(300,130);
    117				Toolkit tool = getToolkit();
    118				Dimension d = tool.getScreenSize();
    119				db.setLocation(d.width / 2 - 150, d.height / 2 - 65);
    120				db.setVisible(true);
    121			}
    122			else {
    123				try {
    124					c_URL = url.openConnection();
    125					c_URL.setDoInput(true);
    126					c_URL.setDoOutput(true);
    127					c_URL.setUseCaches(false);
    128					c_URL.connect();
    129						// 出力
    130					o_stm = c_URL.getOutputStream();
    131					out   = new PrintStream(o_stm);
    132					c     = Integer.parseInt(ans.getText());
    133					out.println("ans=" + a + "," + b + "," + c);
    134					out.close();
    135						// 入力
    136					i_stm = c_URL.getInputStream();
    137					in    = new BufferedReader(new InputStreamReader(i_stm));
    138					str   = in.readLine();
    139					in.close();
    140					if (Integer.parseInt(str) > 0) {
    141						ta.setForeground(Color.black);
    142						ta.setText(" " + name.getText() + "さん,正解です\n");
    143						ta.append(" 続いて,次の問題の答えは?");
    144						a = (int)(100.0 * rn.nextDouble());
    145						b = (int)(100.0 * rn.nextDouble());
    146						ans.setText("");
    147						shiki.setText(Integer.toString(a) + " + " + Integer.toString(b) + " = ");
    148					}
    149					else {
    150						ta.setForeground(Color.red);
    151						ta.setText(" " + name.getText() + "さん,間違っています\n");
    152						ta.append(" もう一度計算してみて下さい");
    153					}
    154				}
    155				catch (IOException e1) {
    156					ta.setForeground(Color.red);
    157					ta.setText("IO Error: " + e1.getMessage());
    158				}
    159			}
    160		}
    161	}
    162	
    163	/*******************/
    164	/* Dialogboxクラス */
    165	/*******************/
    166	class Dialogbox extends JFrame {
    167		Dialogbox(String message)
    168		{
    169			super("Error");
    170			Container cp = getContentPane();
    171			cp.setBackground(Color.white);
    172			JLabel lb = new JLabel(message);
    173			lb.setFont(new Font("TimesRoman", Font.BOLD, 20));
    174			cp.add(lb);
    175			addWindowListener(new WinEnd());
    176		}
    177		class WinEnd extends WindowAdapter
    178		{
    179			public void windowClosing(WindowEvent e) {
    180				setVisible(false);
    181			}
    182		}
    183	}
    			
    023 行目~ 029 行目

      CGI プログラム( check.php,データを送信するプログラム)に基づき,URL クラスのオブジェクトを生成しています.

    123 行目~ 158 行目

      「送信」ボタンがクリックされ,答えや名前に対する入力漏れがなかった場合に対する処理である.
    • 124 行目~ 128 行目: 023 行目~ 029 行目において生成されたオブジェクトに基づき,URLConnection クラスのオブジェクトを生成し,接続している.
    • 130 行目~ 134 行目: 問題と答えを含んだ文字列を出力ストリームに出力した後,出力ストリームを閉じている.例えば,「 3 + 4 = 7 」のような問題であれば,送信される文字列は,「 ans=3,4,7 」となる.
    • 136 行目~ 139 行目: CGI プログラムから送られてきた文字列を読み込み,変数 str に保存した後,入力ストリームを閉じている.
    • 140 行目~ 148 行目: 答えが正しかった場合の処理であり,メッセージと次の問題をテキストエリアに出力している.なお,CGI プログラムからは,答えが正しかった場合は "1" が,間違っていた場合は "0" が送られてくる.
    • 149 行目~ 153 行目: 答えが間違っていた場合の処理であり,メッセージを テキストエリアに出力している.

      以下に示すのは,サーバ側のプログラム check.php のソースです.PHP は,ここでは学修対象としていない言語ですが,簡単に説明しておきます.なお,PHP に関しては,「 PHP 」を参照して下さい.

    01	<?php
    02		$k = 0;
    03		$p = array();
    04		$x = strtok($_POST['ans'], ",");
    05		while ($x !== FALSE) {
    06			$p[$k] = $x;
    07			$x     = strtok(",");
    08			$k++;
    09		}
    10		$a = intval($p[0]);
    11		$b = intval($p[1]);
    12		$c = intval($p[2]);
    13		if (($a + $b) == $c)
    14			printf("1\n");
    15		else
    16			printf("0\n");
    17	?>
    			
    04 行目~ 09 行目

      クライアントから送られてきたデータは,配列 $_POST に入っている.もし,送られてきたデータが,「 ans=3,4,7 」のようなデータであれば,キー 'ans' によってそのデータを参照することができる.その時,$_POST['ans'] の内容は,「 3,4,7 」という文字列になっている.ここでは,その文字列をカンマで分離し,配列 $p に代入している.

    10 行目~ 12 行目

      カンマで分離された各々の文字列を整数に変換している.

    13 行目~ 16 行目

      答えが正しかった場合は文字列 "1\n",また,間違っていた場合は文字列 "0\n" を送信している.

  4. ラジオボタン,チェックボックス,ドロップダウンリスト

      次に,JavaScript に対する説明で使用した「ラジオボタン,チェックボックス,ドロップダウンリスト(チェック)」と同じようなものを Java アプレットを使用して作成してみます.ただし,このアプレット(「AWT の利用」,「Swing の利用」)は,ラジオボタン,チェックボックス,及び,ドロップダウンリストにおいて,状態が変化したときその状態をテキストエリアに表示するだけの機能を持っています.以下に,Java プログラムのソースを示します.

    AWT を利用した場合

    001	import java.applet.*;
    002	import java.awt.*;
    003	import java.awt.event.*;
    004	public class Test extends Applet implements ItemListener
    005	{
    006		TextField name;
    007		Checkbox r1, r2;
    008		Checkbox c1, c2, c3, c4;
    009		Choice ch;
    010		TextArea ta;
    011		/************/
    012		/* 初期設定 */
    013		/************/
    014		public void init()
    015		{
    016						// レイアウト,背景色,フォントなど
    017			setLayout(new BorderLayout(5, 10));
    018			setBackground(new Color(225, 255, 225));
    019			Font f = new Font("TimesRoman", Font.BOLD, 20);
    020			setFont(f);
    021						// 上のパネル
    022			Panel pn1 = new Panel();
    023			pn1.setLayout(new FlowLayout(FlowLayout.CENTER));
    024			add(pn1, BorderLayout.NORTH);
    025			pn1.add(new Label("名前:"));
    026			name = new TextField("", 10);
    027			pn1.add(name);
    028			CheckboxGroup cbg = new CheckboxGroup();
    029			pn1.add(new Label(" 性別:"));
    030			r1 = new Checkbox("男", cbg, false);
    031			pn1.add(r1);
    032			r2 = new Checkbox("女", cbg, false);
    033			pn1.add(r2);
    034			r1.addItemListener(this);
    035			r2.addItemListener(this);
    036						// 中央のパネル
    037			Panel pn2 = new Panel();
    038			add(pn2, BorderLayout.CENTER);
    039			pn2.add(new Label("好きな野菜:"));
    040			c1 = new Checkbox("キャベツ");
    041			pn2.add(c1);
    042			c2 = new Checkbox("大根");
    043			pn2.add(c2);
    044			c3 = new Checkbox("ジャガイモ");
    045			pn2.add(c3);
    046			c4 = new Checkbox("トマト");
    047			pn2.add(c4);
    048			c1.addItemListener(this);
    049			c2.addItemListener(this);
    050			c3.addItemListener(this);
    051			c4.addItemListener(this);
    052			pn2.add(new Label(" 好きな果物:"));
    053			ch = new Choice();
    054			ch.add("蜜柑");
    055			ch.add("林檎");
    056			ch.add("葡萄");
    057			pn2.add(ch);
    058			ch.addItemListener(this);
    059						// 下のパネル
    060			Panel pn3 = new Panel();
    061			add(pn3, BorderLayout.SOUTH);
    062			ta = new TextArea(4, 50);
    063			pn3.add(ta);
    064		}
    065	
    066		/******************************/
    067		/* 上,左,下,右の余白の設定 */
    068		/******************************/
    069		public Insets getInsets()
    070		{
    071			return new Insets(10, 10, 10, 10);
    072		}
    073		/************************/
    074		/* 選択されたときの処理 */
    075		/************************/
    076		public void itemStateChanged(ItemEvent e)
    077		{
    078			int sw = 0;
    079			ta.setText("名前:" + name.getText() + "\n");
    080			if (r1.getState())
    081				ta.append("性別: 男\n");
    082			else if (r2.getState())
    083				ta.append("性別: 女\n");
    084			if (c1.getState()) {
    085				sw = 1;
    086				ta.append("好きな野菜: キャベツ");
    087			}
    088			if (c2.getState()) {
    089				if (sw == 0) {
    090					sw = 1;
    091					ta.append("好きな野菜: 大根");
    092				}
    093				else
    094					ta.append(",大根");
    095			}
    096			if (c3.getState()) {
    097				if (sw == 0) {
    098					sw = 1;
    099					ta.append("好きな野菜: ジャガイモ");
    100				}
    101				else
    102					ta.append(",ジャガイモ");
    103			}
    104			if (c4.getState()) {
    105				if (sw == 0) {
    106					sw = 1;
    107					ta.append("好きな野菜: トマト");
    108				}
    109				else
    110					ta.append(",トマト");
    111			}
    112			if (sw > 0) {
    113				sw = 0;
    114				ta.append("\n");
    115			}
    116			if (ch.getSelectedIndex() >= 0)
    117				ta.append("好きな果物: " + ch.getSelectedItem() + "\n");
    118		}
    119	}
    			
    004 行目

      ラジオボタンやチェックボックスにおいて,選択項目が変化したときの処理を行うため,インタフェース ItemListener を継承

    028 行目~ 035 行目

      Panel クラスのオブジェクト pn1 に,CheckboxGroup クラスCheckbox クラスを利用して,性別を選択するためのラジオボタンを追加している.なお,各ラジオボタンには,項目が選択されたときの処理を行うため,ItemListener を付加している( 034 行目~ 035 行目).

    040 行目~ 051 行目

      Panel クラスのオブジェクト pn2 に,Checkbox クラスを利用して,好きな野菜を選択するためのチェックボックスを追加している.

    053 行目~ 058 行目

      Panel クラスのオブジェクト pn2 に,Choice クラスを利用して,好きな果物を選択するためのドロップダウンリストを追加している.

    062 行目~ 063 行目

      Panel クラスのオブジェクト pn3 に,TextArea クラスを利用して,テキストエリアを追加している.なお,このテキストエリアには,ラジオボタン,チェックボックス,または,ドロップダウンリストの項目が選択されたときの処理を行うメソッドによって,その時点における各項目等の状態が出力される.

    076 行目~ 118 行目

      ラジオボタン,チェックボックス,または,ドロップダウンリストの項目が選択されたときの処理を行うメソッドである.TextField オブジェクト name の内容を TextArea オブジェクト ta に出力( 079 行目)した後,ラジオボタン( 080 行目~ 083 行目),チェックボックス( 084 行目~ 115 行目),及び,ドロップダウンリスト( 116 行目~ 117 行目)の状態を調べ,その状態を同じく ta に出力している.

    Swing を利用した場合

    001	import javax.swing.*;
    002	import java.awt.*;
    003	import java.awt.event.*;
    004	public class Test extends JApplet implements ActionListener
    005	{
    006		JTextField name;
    007		JRadioButton r1, r2;
    008		JCheckBox c1, c2, c3, c4;
    009		JComboBox <String> ch;
    010		JTextArea ta;
    011		/************/
    012		/* 初期設定 */
    013		/************/
    014		public void init()
    015		{
    016						// レイアウト,背景色,フォントなど
    017			Container cp = getContentPane();
    018			cp.setBackground(new Color(225, 255, 225));
    019			Font f = new Font("TimesRoman", Font.BOLD, 20);
    020						// 上のパネル
    021			JPanel pn1 = new JPanel();
    022			pn1.setBackground(new Color(225, 255, 225));
    023			pn1.setLayout(new FlowLayout(FlowLayout.CENTER));
    024			cp.add(pn1, BorderLayout.NORTH);
    025			JLabel lb1 = new JLabel("名前:");
    026			lb1.setFont(f);
    027			pn1.add(lb1);
    028			name = new JTextField("", 10);
    029			name.setFont(f);
    030			name.setBackground(Color.white);
    031			pn1.add(name);
    032			ButtonGroup gp = new ButtonGroup();
    033			JLabel lb2 = new JLabel(" 性別:");
    034			lb2.setFont(f);
    035			pn1.add(lb2);
    036			r1 = new JRadioButton("男");
    037			r1.setFont(f);
    038			r1.setBackground(new Color(225, 255, 225));
    039			gp.add(r1);
    040			pn1.add(r1);
    041			r2 = new JRadioButton("女");
    042			r2.setFont(f);
    043			r2.setBackground(new Color(225, 255, 225));
    044			gp.add(r2);
    045			pn1.add(r2);
    046			r1.addActionListener(this);
    047			r2.addActionListener(this);
    048						// 中央のパネル
    049			JPanel pn2 = new JPanel();
    050			pn2.setBackground(new Color(225, 255, 225));
    051			cp.add(pn2, BorderLayout.CENTER);
    052			JLabel lb3 = new JLabel("好きな野菜:");
    053			lb3.setFont(f);
    054			pn2.add(lb3);
    055			c1 = new JCheckBox("キャベツ");
    056			c1.setFont(f);
    057			c1.setBackground(new Color(225, 255, 225));
    058			pn2.add(c1);
    059			c2 = new JCheckBox("大根");
    060			c2.setFont(f);
    061			c2.setBackground(new Color(225, 255, 225));
    062			pn2.add(c2);
    063			c3 = new JCheckBox("ジャガイモ");
    064			c3.setFont(f);
    065			c3.setBackground(new Color(225, 255, 225));
    066			pn2.add(c3);
    067			c4 = new JCheckBox("トマト");
    068			c4.setFont(f);
    069			c4.setBackground(new Color(225, 255, 225));
    070			pn2.add(c4);
    071			c1.addActionListener(this);
    072			c2.addActionListener(this);
    073			c3.addActionListener(this);
    074			c4.addActionListener(this);
    075			JLabel lb4 = new JLabel(" 好きな果物:");
    076			lb4.setFont(f);
    077			pn2.add(lb4);
    078			ch = new JComboBox <String> ();
    079			ch.setFont(f);
    080			ch.setBackground(Color.white);
    081			ch.addItem("蜜柑");
    082			ch.addItem("林檎");
    083			ch.addItem("葡萄");
    084			pn2.add(ch);
    085			ch.addActionListener(this);
    086						// 下のパネル
    087			JPanel pn3 = new JPanel();
    088			pn3.setBackground(new Color(225, 255, 225));
    089			cp.add(pn3, BorderLayout.SOUTH);
    090			ta = new JTextArea(4, 30);
    091			ta.setFont(f);
    092			ta.setBackground(Color.white);
    093			JScrollPane sp = new JScrollPane(ta);
    094			pn3.add(sp);
    095		}
    096	
    097		/******************************/
    098		/* 上,左,下,右の余白の設定 */
    099		/******************************/
    100		public Insets getInsets()
    101		{
    102			return new Insets(10, 10, 10, 10);
    103		}
    104		/************************/
    105		/* 選択されたときの処理 */
    106		/************************/
    107		public void actionPerformed(ActionEvent e)
    108		{
    109			int sw = 0;
    110			ta.setText("名前:" + name.getText() + "\n");
    111			if (r1.isSelected())
    112				ta.append("性別: 男\n");
    113			else if (r2.isSelected())
    114				ta.append("性別: 女\n");
    115			if (c1.isSelected()) {
    116				sw = 1;
    117				ta.append("好きな野菜: キャベツ");
    118			}
    119			if (c2.isSelected()) {
    120				if (sw == 0) {
    121					sw = 1;
    122					ta.append("好きな野菜: 大根");
    123				}
    124				else
    125					ta.append(",大根");
    126			}
    127			if (c3.isSelected()) {
    128				if (sw == 0) {
    129					sw = 1;
    130					ta.append("好きな野菜: ジャガイモ");
    131				}
    132				else
    133					ta.append(",ジャガイモ");
    134			}
    135			if (c4.isSelected()) {
    136				if (sw == 0) {
    137					sw = 1;
    138					ta.append("好きな野菜: トマト");
    139				}
    140				else
    141					ta.append(",トマト");
    142			}
    143			if (sw > 0) {
    144				sw = 0;
    145				ta.append("\n");
    146			}
    147			if (ch.getSelectedIndex() >= 0)
    148				ta.append("好きな果物: " + ch.getSelectedItem() + "\n");
    149		}
    150	}
    			
    004 行目

      ラジオボタンやチェックボックスにおいて,選択項目が変化したときの処理を行うため,インタフェース ActionListener を継承

    032 行目~ 047 行目

      JPanel クラスのオブジェクト pn1 に,ButtonGroup クラス(ラジオボタンをグループ化するためのクラス)と JRadioButton クラスを利用して,性別を選択するためのラジオボタンを追加している.なお,各ラジオボタンには,項目が選択されたときの処理を行うため,ActionListener を付加している( 046 行目~ 047 行目).

    055 行目~ 074 行目

      JPanel クラスのオブジェクト pn2 に,JCheckBox クラスを利用して,好きな野菜を選択するためのチェックボックスを追加している.

    078 行目~ 085 行目

      JPanel クラスのオブジェクト pn2 に,JComboBox クラスを利用して,好きな果物を選択するためのドロップダウンリストを追加している.

    090 行目~ 094 行目

      テキストエリアに自動的にスクロールバーを貼り付けるため,JTextArea クラスのオブジェクト ta に基づき,JScrollPane クラスのオブジェクト sp を生成し,それを JPanel クラスのオブジェクト pn3 に追加している.なお,このテキストエリアには,ラジオボタン,チェックボックス,または,ドロップダウンリストの項目が選択されたときの処理を行うメソッドによって,その時点における各項目等の状態が出力される.

    107 行目~ 149 行目

      ラジオボタン,チェックボックス,または,ドロップダウンリストの項目が選択されたときの処理を行うメソッドである.JTextField オブジェクト name の内容を JTextArea オブジェクト ta に出力( 110 行目)した後,ラジオボタン( 111 行目~ 114 行目),チェックボックス( 115 行目~ 146 行目),及び,ドロップダウンリスト( 147 行目~ 148 行目)の状態を調べ,その状態を同じく ta に出力している.

  5. お絵かき

      この例(「AWT の利用」,「Swing の利用」)は,マウスのドラッグを利用した簡単なお絵かきツールです.アプレットの画面上でマウスをドラッグすると,その動きに沿った自由曲線が描画されます.

    AWT を利用した場合

    01	import java.awt.*;
    02	import java.awt.event.*;
    03	import java.applet.*;
    04	import java.util.*;
    05	
    06	public class Test2 extends Applet implements MouseMotionListener {
    07		Vector <Point> v = new Vector <Point> ();
    08						// 初期設定
    09		public void init()
    10		{
    11			setBackground(Color.white);
    12			addMouseMotionListener(this);
    13		}
    14						// マウスイベントの処理
    15		public void mouseDragged(MouseEvent e)
    16		{
    17			v.add(new Point(e.getX(), e.getY()));
    18			repaint();
    19		}
    20		public void mouseMoved(MouseEvent e)
    21		{
    22			if (v.size() > 0) {
    23				Point p = (Point)v.get(v.size()-1);
    24				if (p.x >= 0)
    25					v.add(new Point(-1, -1));
    26			}
    27		}
    28						// 描画
    29		public void paint (Graphics g)
    30		{
    31			int i1;
    32			Point p1, p2;
    33			if (v.size() > 0) {
    34				p1 = (Point)v.get(0);
    35				for (i1 = 1; i1 < v.size(); i1++) {
    36					p2 = (Point)v.get(i1);
    37					if (p1.x >= 0 && p2.x >= 0)
    38						g.drawLine(p1.x, p1.y, p2.x, p2.y);
    39					p1 = p2;
    40				}
    41			}
    42		}
    43	}
    			
    06 行目

      マウスが動いたときに発生するイベントの処理を行うため,インタフェース MouseMotionListener を継承

    07 行目

      Vector クラスのオブジェクトを生成している.Vector クラスは,可変長の配列を処理するためのクラスである.その要素として,様々なオブジェクトを利用可能であるが,ここでは,「 <Point> 」の指定により,Point クラスのオブジェクトが入る.なお,Vector クラスのメソッドは同期をとるため,単一のスレッドから Vector にアクセスする場合は,ArrayList クラスを使用するべきである.

    11 行目~ 12 行目

      背景色を白とし,MouseMotionListener を追加している.

    15 行目~ 19 行目

      マウスでドラッグしたときの処理であり,現在のマウスの位置から Point クラスのオブジェクトを生成し,それを,Vector クラスのオブジェクト v に追加している( 17 行目).その後,画面を再描画している( paint メソッドの実行).

    20 行目~ 27 行目

      マウスをドラッグしないで移動したときの処理である.ドラッグが行われているとき,刻々のマウスの位置を Vector クラスのオブジェクト v に保存し,それらを直線で繋いで描画するだけでは,すべての点が繋がった一本の曲線になってしまう.ドラッグして一つの曲線を描き,マウスを移動して,他の曲線を描きたいような場合は,Vector クラスのオブジェクト v の中に二つの曲線を区切るような情報を入れておく必要がある.このプログラムでは,ドラッグが終了した時,(-1, -1) という点を v に保存することによって対処している,

    29 行目~ 42 行目

      描画を行う Applet クラスのメソッド paint をオーバーライドしている.このように,描画は,Graphics クラスのメソッドを使用して行われる.基本的には,Vector クラスのオブジェクト v に保存されている点を順に直線で結んでいる( 38 行目)だけである.ただし,上で述べたように,点の座標が (-1, -1) である場合は,その点の前後を結ばないようにしている.

    Swing を利用した場合

    01	import java.awt.*;
    02	import java.awt.event.*;
    03	import javax.swing.*;
    04	import java.util.*;
    05						// 初期設定
    06	public class Test2 extends JApplet
    07	{
    08		public void init()
    09		{
    10			Test_2_Panel pn = new Test_2_Panel();
    11			getContentPane().add(pn);
    12		}
    13	}
    14						// 描画パネル
    15	class Test_2_Panel extends JPanel implements MouseMotionListener
    16	{
    17		ArrayList <Point> v = new ArrayList <Point> ();
    18								// コンストラクタ
    19		Test_2_Panel()
    20		{
    21			addMouseMotionListener(this);
    22			setBackground(Color.white);
    23		}
    24								// マウスイベントの処理
    25		public void mouseDragged(MouseEvent e)
    26		{
    27			v.add(new Point(e.getX(), e.getY()));
    28			repaint();
    29		}
    30		public void mouseMoved(MouseEvent e)
    31		{
    32			if (v.size() > 0) {
    33				Point p = (Point)v.get(v.size()-1);
    34				if (p.x >= 0)
    35					v.add(new Point(-1, -1));
    36			}
    37		}
    38								// 描画
    39		public void paintComponent (Graphics g)
    40		{
    41			super.paintComponent(g);   // 親クラスの描画(必ず必要)
    42			int i1;
    43			Point p1, p2;
    44			if (v.size() > 0) {
    45				p1 = (Point)v.get(0);
    46				for (i1 = 1; i1 < v.size(); i1++) {
    47					p2 = (Point)v.get(i1);
    48					if (p1.x >= 0 && p2.x >= 0)
    49						g.drawLine(p1.x, p1.y, p2.x, p2.y);
    50					p1 = p2;
    51				}
    52			}
    53		}
    54	}
    			
    10 行目~ 11 行目

      Test_2_Panel クラス(クラス定義は 15 行目~ 54 行目,JPanel を継承)のオブジェクトを生成し,JRootPane クラスのオブジェクトに追加している.

    15 行目

      JPanel クラスを継承すると共に,マウスが動いたときに発生するイベントの処理を行うため,インタフェース MouseMotionListener を継承している.

    17 行目

      ArrayList クラスのオブジェクトを生成している.ArrayList クラスは,可変長の配列を処理するためのクラスである.その要素として,様々なオブジェクトを利用可能であるが,ここでは,「 <Point> 」の指定により,Point クラスのオブジェクトが入る.なお,Vector クラスを使用することも可能であるが,Vector クラスのメソッドは同期をとるため,単一のスレッドから Vector にアクセスする場合は,この例のように,ArrayList クラスを使用するべきである.

    21 行目~ 22 行目

      背景色を白とし,MouseMotionListener を追加している.

    25 行目~ 29 行目

      マウスでドラッグしたときの処理であり,現在のマウスの位置から Point クラスのオブジェクトを生成し,それを,ArrayList クラスのオブジェクト v に追加している( 27 行目).その後,画面を再描画している( paintComponent メソッドの実行).

    30 行目~ 37 行目

      マウスをドラッグしないで移動したときの処理である.ドラッグが行われているとき,刻々のマウスの位置を ArrayList クラスのオブジェクト v に保存し,それらを直線で繋いで描画するだけでは,すべての点が繋がった一本の曲線になってしまう.ドラッグして一つの曲線を描き,マウスを移動して,他の曲線を描きたいような場合は,ArrayList クラスのオブジェクト v の中に二つの曲線を区切るような情報を入れておく必要がある.このプログラムでは,ドラッグが終了した時,(-1, -1) という点を v に保存することによって対処している,

    39 行目~ 53 行目

      描画を行う JPanel クラスのメソッド paintComponent をオーバーライドしている.このように,描画は,Graphics クラスのメソッドを使用して行われる.親クラスの描画を行った( 41 行目)後,基本的には,ArrayList クラスのオブジェクト v に保存されている点を順に直線で結んでいる( 49 行目)だけである.ただし,上で述べたように,点の座標が (-1, -1) である場合は,その点の前後を結ばないようにしている.

      以下に示す例は,上で示した例にメニューを付加し,多少お絵かきソフトらしく修正したものです.始点と終点をクリックすることによって直線を描くことができます.また,線の太さや色の変更も可能です.ここをクリックするとアプレット版が表示されますので,適当な図を描いてみてください.ここでは,アプリケーション版,アプレット版,いずれも Swing を利用しています.

    アプリケーション版

    001	/****************************/
    002	/* main program             */
    003	/*      coded by Y.Suganuma */
    004	/****************************/
    005	public class Main {
    006		public static void main (String[] args)
    007		{
    008			PaintPanel pt = new PaintPanel("ペイント");
    009		}
    010	}
    011	
    012	/****************************/
    013	/* PaintPanel クラス        */
    014	/*      coded by Y.Suganuma */
    015	/****************************/
    016	import java.awt.*;
    017	import javax.swing.*;
    018	import java.awt.event.*;
    019	
    020	class PaintPanel extends JFrame
    021	{
    022		PaintPanel(String name)
    023		{
    024						// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    025			super(name);
    026						// Windowの大きさ
    027			setSize(500, 300);
    028						// ウィンドウを表示
    029			setVisible(true);
    030						// MainPanel オブジェクトを ContentPane に追加
    031			MainPanel pn = new MainPanel(this);
    032			getContentPane().add(pn);   
    033			setVisible(true);   // Window を表示
    034						// イベントの登録
    035			addWindowListener(new WinEnd());
    036		}
    037		/************/
    038		/* 終了処理 */
    039		/************/
    040		class WinEnd extends WindowAdapter
    041		{
    042			public void windowClosing(WindowEvent e) {
    043				System.exit(0);
    044			}
    045		}
    046	}
    047	
    048	/****************************/
    049	/* MainPanel クラス         */
    050	/*      coded by Y.Suganuma */
    051	/****************************/
    052	import java.awt.*;
    053	import javax.swing.*;
    054	
    055	class MainPanel extends JPanel
    056	{
    057		MainPanel(PaintPanel pt)
    058		{
    059						// 背景色の設定
    060			setBackground(Color.white);
    061						// レイアウトマネージャの停止
    062			setLayout(null);
    063						// Windowの大きさの取得
    064			Dimension size = pt.getSize();
    065			Insets insets = pt.getInsets();
    066			size.width = size.width - insets.left - insets.right;
    067			size.height = size.height - insets.top - insets.bottom;
    068						// Draw パネルの追加
    069			int ct_width = 140;
    070			Draw dr = new Draw();
    071			add(dr);   
    072			dr.setSize(size.width - ct_width, size.height);
    073			dr.setLocation(ct_width, 0);
    074						// Control パネルの追加
    075			Control ct = new Control(dr);
    076			add(ct);
    077			ct.setSize(ct_width, size.height);
    078			ct.setLocation(0, 0);
    079		}
    080	}
    081	
    082	/****************************/
    083	/* Draw クラス              */
    084	/*      coded by Y.Suganuma */
    085	/****************************/
    086	import java.awt.*;
    087	import java.awt.geom.*;
    088	import java.awt.event.*;
    089	import javax.swing.*;
    090	import java.util.*;
    091	
    092	class Draw extends JPanel implements MouseListener, MouseMotionListener
    093	{
    094		int type = 0;   // 図形の種類(0:自由曲線,1:直線)
    095		Color cl = Color.black;   // 描画色
    096		Stroke bs = new BasicStroke(1.0f);   // 線のタイプ
    097		ArrayList <Segment> s = new ArrayList <Segment> ();   // 描画データ
    098		ArrayList <Point> v = new ArrayList <Point> ();   // 描画位置データ
    099		boolean draw = false;   // 作図中か否か
    100						// コンストラクタ
    101		Draw()
    102		{
    103								// 背景色の設定
    104			setBackground(Color.white);
    105								// MouseListenerの追加
    106			addMouseListener(this);
    107								// MouseMotionListenerの追加
    108			addMouseMotionListener(this);
    109		}
    110						// MouseMotionListenerに対する処理
    111		public void mouseDragged(MouseEvent e)
    112		{
    113								// 自由曲線
    114			if (type == 0) {
    115				draw = true;
    116				v.add(new Point(e.getX(), e.getY()));
    117				repaint();
    118			}
    119		}
    120		public void mouseMoved(MouseEvent e)
    121		{
    122								// 自由曲線
    123			if (type == 0) {
    124				if (draw) {
    125					draw = false;
    126					Segment sg = new Segment(type, cl, bs, v);
    127					s.add(sg);
    128					v.clear();
    129				}
    130			}
    131		}
    132						// MouseListenerによる処理
    133		public void mouseClicked(MouseEvent e)
    134		{
    135								// 直線
    136			if (type == 1) {
    137										// 描画と保存
    138				if (draw) {
    139					v.add(new Point(e.getX(), e.getY()));
    140					repaint();
    141				}
    142										// スタート
    143				else {
    144					draw = true;
    145					v.add(new Point(e.getX(), e.getY()));
    146					type = -type;
    147					repaint();
    148				}
    149			}
    150		}
    151		public void mousePressed(MouseEvent e) {}
    152		public void mouseReleased(MouseEvent e) {}
    153		public void mouseEntered(MouseEvent e) {}
    154		public void mouseExited(MouseEvent e) {}
    155						// 描画
    156		public void paintComponent(Graphics g)
    157		{
    158			super.paintComponent(g);   // 親クラスの描画
    159								// Graphics2Dの取得
    160			Graphics2D g2 = (Graphics2D)g;
    161								// 既に描いた図形の描画
    162			for (int i1 = 0; i1 < s.size(); i1++) {
    163				g2.setStroke(s.get(i1).bs);
    164				g2.setColor(s.get(i1).cl);
    165										// 自由曲線,直線
    166				if (s.get(i1).type == 0 || s.get(i1).type == 1) {
    167					Point p1, p2;
    168					p1 = s.get(i1).v.get(0);
    169					for (int i2 = 1; i2 < s.get(i1).v.size(); i2++) {
    170						p2 = s.get(i1).v.get(i2);
    171						g2.draw(new Line2D.Double(p1.x, p1.y, p2.x, p2.y));
    172						p1 = p2;
    173					}
    174				}
    175			}
    176								// 作図中
    177			if (draw) {
    178				g2.setStroke(bs);
    179				g2.setColor(cl);
    180										// スタート
    181				if (type < 0) {
    182					type = -type;
    183					g2.setColor(Color.black);
    184					g2.setStroke(new BasicStroke(1.0f));
    185					Point p = v.get(0);
    186					g2.draw(new Line2D.Double(p.x-10, p.y, p.x+10, p.y));
    187					g2.draw(new Line2D.Double(p.x, p.y-10, p.x, p.y+10));
    188				}
    189										// 自由曲線,直線
    190				else if (type == 0 || type == 1) {
    191					Point p1, p2;
    192					p1 = v.get(0);
    193					for (int i1 = 1; i1 < v.size(); i1++) {
    194						p2 = v.get(i1);
    195						g2.draw(new Line2D.Double(p1.x, p1.y, p2.x, p2.y));
    196						p1 = p2;
    197					}
    198					if (type == 1) {
    199						draw = false;
    200						Segment sg = new Segment(type, cl, bs, v);
    201						s.add(sg);
    202						v.clear();
    203					}
    204				}
    205			}
    206		}
    207	}
    208	
    209	/****************************/
    210	/* Control クラス           */
    211	/*      coded by Y.Suganuma */
    212	/****************************/
    213	import java.awt.*;
    214	import javax.swing.*;
    215	import java.awt.event.*;
    216	
    217	class Control extends JPanel
    218	{
    219		Draw dr;   // Draw クラス
    220		JButton type0, type1, color1, color2, line1, line2;
    221						// コンストラクタ
    222		Control(Draw dr)
    223		{
    224			this.dr = dr;
    225								// 背景色の設定
    226			setBackground(new Color(238, 255, 238));
    227								// ボタンの配置
    228			type0 = new JButton("曲線");
    229			type0.addMouseListener(new ClickMouse());
    230			add(type0);
    231	
    232			type1 = new JButton("直線");
    233			type1.addMouseListener(new ClickMouse());
    234			add(type1);
    235	
    236			color1 = new JButton("赤");
    237			color1.setBackground(Color.red);
    238			color1.addMouseListener(new ClickMouse());
    239			add(color1);
    240	
    241			color2 = new JButton("緑");
    242			color2.setBackground(Color.green);
    243			color2.addMouseListener(new ClickMouse());
    244			add(color2);
    245	
    246			line1 = new JButton("細い");
    247			line1.setBackground(Color.yellow);
    248			line1.addMouseListener(new ClickMouse());
    249			add(line1);
    250	
    251			line2 = new JButton("太い");
    252			line2.setBackground(Color.yellow);
    253			line2.addMouseListener(new ClickMouse());
    254			add(line2);
    255		}
    256						// ボタンが押されたときの処理
    257		class ClickMouse extends MouseAdapter {
    258			public void mouseClicked(MouseEvent e)
    259			{
    260				if (e.getSource() == type0)
    261					dr.type = 0;
    262				else if (e.getSource() == type1)
    263					dr.type = 1;
    264				else if (e.getSource() == color1)
    265					dr.cl = Color.red;
    266				else if (e.getSource() == color2)
    267					dr.cl = Color.green;
    268				else if (e.getSource() == line1)
    269					dr.bs = new BasicStroke(1.0f);
    270				else if (e.getSource() == line2)
    271					dr.bs = new BasicStroke(5.0f);
    272			}
    273		}
    274	}
    275	
    276	/****************************/
    277	/* Segment クラス           */
    278	/*      coded by Y.Suganuma */
    279	/****************************/
    280	import java.awt.*;
    281	import javax.swing.*;
    282	import java.util.*;
    283	
    284	class Segment
    285	{
    286		int type;   // 図形の種類(0:自由曲線,1:直線,2:矩形,3:塗りつぶした矩形)
    287		Color cl;   // 描画色
    288		Stroke bs;   // 線のタイプ
    289		ArrayList <Point> v = new ArrayList <Point> ();   // 描画位置データ
    290						// コンストラクタ
    291		Segment(int type, Color cl, Stroke bs, ArrayList <Point> v)
    292		{
    293			this.type = type;
    294			this.cl = cl;
    295			this.bs = bs;
    296			this.v.addAll(v);
    297		}
    298	}
    			
    008 行目

      PaintPanel クラス(クラス定義は 016 行目~ 046 行目,JFrame を継承)のオブジェクトを生成している.この結果,描画を行うための新しい Window が表示される.

    031 行目~ 032 行目

      MainPanel クラス(クラス定義は 052 行目~ 080 行目,JPanel を継承)のオブジェクトを生成し,JRootPane クラスのオブジェクトに追加している.

    035 行目

      Window の「×」ボタンをクリックしたとき,Window を終了させるために WindowListener を追加している.

    040 行目~ 045 行目

      Window の「×」ボタンをクリックしたときの処理( Window の終了).

    062 行目

      レイアウトマネージャを無効にしている.その結果,コンポーネントを任意の位置に,任意の大きさで配置できるようになる.

    064 行目~ 067 行目

      Window の大きさ( 064 行目)から,枠等のサイズ( 065 行目)を引き,実際の表示領域を Dimension クラスのオブジェクト size に設定している.

    069 行目~ 073 行目

      MainPanel の右側に,実際に描画を行うパネル( Draw クラス,086 行目~ 207 行目)を追加している.

    075 行目~ 078 行目

      MainPanel の左側に,線の太さ,線の色等を制御するパネル( Control クラス,213 行目~ 274 行目)を追加している.

    111 行目~ 119 行目

      マウスでドラッグしたときの処理であり,自由曲線を描く場合( type = 0 )は,先に述べた例と同様,現在のマウスの位置から Point クラスのオブジェクトを生成し,それを,ArrayList クラスのオブジェクト v に追加している.

    120 行目~ 131 行目

      マウスが移動したときの処理である.自由曲線を描く場合( type = 0 )で,かつ,それまでドラッグしていた場合( draw = true )は,描画を中止し( 125 行目),ArrayList クラスのオブジェクト v に保存されている自由曲線データと線の種類等に関するデータに基づき,Segment クラス( 280 行目~ 298 行目)のオブジェクトを生成し,ArrayList クラスのオブジェクト s に追加している.また,ArrayList クラスのオブジェクト v の内容をクリアしている.

    133 行目~ 150 行目

      マウスをクリックしたときの処理である.直線を描く場合( type = 1 )において,描画中の場合( draw = true )は,終点を ArrayList クラスのオブジェクト v に追加し,再描画している( 139 行目~ 140 行目).また,描画中でない場合( draw = false )は,始点を ArrayList クラスのオブジェクト v に追加し,再描画している( 144 行目~ 147 行目).

    151 行目~ 154 行目

      これらの行は,MouseListener に定義されている関数であり,実際に処理する内容はないが.このような形で定義しておく必要がある.

    160 行目

      Graphics2D クラスのオブジェクトを生成している.Graphics2D クラスは,線の幅等を設定するために必要になる.

    162 行目~ 175 行目

      ArrayList クラスのオブジェクト s に保存されている Segment クラスのオブジェクトに基づき,自由曲線または直線を描画している.

    181 行目~ 188 行目

      type の値が負であることは,146 行目より,直線の始点を指定したことを意味している.ここでは,黒い細い線で,始点に十字を描いている.

    191 行目~ 197 行目

      ArrayList クラスのオブジェクト v に保存された点を結ぶ直線を描いている.

    198 行目~ 203 行目

      ArrayList クラスのオブジェクト v に保存されている直線データと線の種類等に関するデータに基づき,Segment クラスのオブジェクトを生成し,ArrayList クラスのオブジェクト s に追加している.また,ArrayList クラスのオブジェクト v の内容をクリアしている.

    228 行目~ 254 行目

      線の種類,色,太さを変更するために,JButton クラスのオブジェクトを追加している.

    257 行目~ 273 行目

      上で設定した各ボタンがクリックされたときの処理である.クリックされたボタンに従って,Draw クラスのオブジェクトのプロパティ type(線の種類),cl(線の色),または,bs(線の太さ)の値を再設定している.

    280 行目~ 298 行目

      線の種類( type ),線の色( cl ),線の太さ( bs ),線の位置( v )をプロパティとして持つクラスである.

    アプレット版( Swing )

    001	/****************************/
    002	/* PaintPanel クラス        */
    003	/*      coded by Y.Suganuma */
    004	/****************************/
    005	import java.awt.*;
    006	import javax.swing.*;
    007	import java.awt.event.*;
    008	
    009	public class PaintPanel extends JApplet
    010	{
    011		public void init()
    012		{
    013						// MainPanel オブジェクトを ContentPane に追加
    014			MainPanel pn = new MainPanel(this);
    015			getContentPane().add(pn);   
    016		}
    017	}
    018	
    019	/****************************/
    020	/* MainPanel クラス         */
    021	/*      coded by Y.Suganuma */
    022	/****************************/
    023	import java.awt.*;
    024	import javax.swing.*;
    025	
    026	class MainPanel extends JPanel
    027	{
    028		MainPanel(PaintPanel pt)
    029		{
    030						// 背景色の設定
    031			setBackground(Color.white);
    032						// レイアウトマネージャの停止
    033			setLayout(null);
    034						// Windowの大きさの取得
    035			Dimension size = pt.getSize();
    036			Insets insets = pt.getInsets();
    037			size.width = size.width - insets.left - insets.right;
    038			size.height = size.height - insets.top - insets.bottom;
    039						// Draw パネルの追加
    040			int ct_width = 140;
    041			Draw dr = new Draw();
    042			add(dr);   
    043			dr.setSize(size.width - ct_width, size.height);
    044			dr.setLocation(ct_width, 0);
    045						// Control パネルの追加
    046			Control ct = new Control(dr);
    047			add(ct);
    048			ct.setSize(ct_width, size.height);
    049			ct.setLocation(0, 0);
    050		}
    051	}
    052	
    053	/****************************/
    054	/* Draw クラス              */
    055	/*      coded by Y.Suganuma */
    056	/****************************/
    057	import java.awt.*;
    058	import java.awt.geom.*;
    059	import java.awt.event.*;
    060	import javax.swing.*;
    061	import java.util.*;
    062	
    063	class Draw extends JPanel implements MouseListener, MouseMotionListener
    064	{
    065		int type = 0;   // 図形の種類(0:自由曲線,1:直線)
    066		Color cl = Color.black;   // 描画色
    067		Stroke bs = new BasicStroke(1.0f);   // 線のタイプ
    068		ArrayList <Segment> s = new ArrayList <Segment> ();   // 描画データ
    069		ArrayList <Point> v = new ArrayList <Point> ();   // 描画位置データ
    070		boolean draw = false;   // 作図中か否か
    071						// コンストラクタ
    072		Draw()
    073		{
    074								// 背景色の設定
    075			setBackground(Color.white);
    076								// MouseListenerの追加
    077			addMouseListener(this);
    078								// MouseMotionListenerの追加
    079			addMouseMotionListener(this);
    080		}
    081						// MouseMotionListenerに対する処理
    082		public void mouseDragged(MouseEvent e)
    083		{
    084								// 自由曲線
    085			if (type == 0) {
    086				draw = true;
    087				v.add(new Point(e.getX(), e.getY()));
    088				repaint();
    089			}
    090		}
    091		public void mouseMoved(MouseEvent e)
    092		{
    093								// 自由曲線
    094			if (type == 0) {
    095				if (draw) {
    096					draw = false;
    097					Segment sg = new Segment(type, cl, bs, v);
    098					s.add(sg);
    099					v.clear();
    100				}
    101			}
    102		}
    103						// MouseListenerによる処理
    104		public void mouseClicked(MouseEvent e)
    105		{
    106								// 直線
    107			if (type == 1) {
    108										// 描画と保存
    109				if (draw) {
    110					v.add(new Point(e.getX(), e.getY()));
    111					repaint();
    112				}
    113										// スタート
    114				else {
    115					draw = true;
    116					v.add(new Point(e.getX(), e.getY()));
    117					type = -type;
    118					repaint();
    119				}
    120			}
    121		}
    122		public void mousePressed(MouseEvent e) {}
    123		public void mouseReleased(MouseEvent e) {}
    124		public void mouseEntered(MouseEvent e) {}
    125		public void mouseExited(MouseEvent e) {}
    126						// 描画
    127		public void paintComponent(Graphics g)
    128		{
    129			super.paintComponent(g);   // 親クラスの描画
    130								// Graphics2Dの取得
    131			Graphics2D g2 = (Graphics2D)g;
    132								// 既に描いた図形の描画
    133			for (int i1 = 0; i1 < s.size(); i1++) {
    134				g2.setStroke(s.get(i1).bs);
    135				g2.setColor(s.get(i1).cl);
    136										// 自由曲線,直線
    137				if (s.get(i1).type == 0 || s.get(i1).type == 1) {
    138					Point p1, p2;
    139					p1 = s.get(i1).v.get(0);
    140					for (int i2 = 1; i2 < s.get(i1).v.size(); i2++) {
    141						p2 = s.get(i1).v.get(i2);
    142						g2.draw(new Line2D.Double(p1.x, p1.y, p2.x, p2.y));
    143						p1 = p2;
    144					}
    145				}
    146			}
    147								// 作図中
    148			if (draw) {
    149				g2.setStroke(bs);
    150				g2.setColor(cl);
    151										// スタート
    152				if (type < 0) {
    153					type = -type;
    154					g2.setColor(Color.black);
    155					g2.setStroke(new BasicStroke(1.0f));
    156					Point p = v.get(0);
    157					g2.draw(new Line2D.Double(p.x-10, p.y, p.x+10, p.y));
    158					g2.draw(new Line2D.Double(p.x, p.y-10, p.x, p.y+10));
    159				}
    160										// 自由曲線,直線
    161				else if (type == 0 || type == 1) {
    162					Point p1, p2;
    163					p1 = v.get(0);
    164					for (int i1 = 1; i1 < v.size(); i1++) {
    165						p2 = v.get(i1);
    166						g2.draw(new Line2D.Double(p1.x, p1.y, p2.x, p2.y));
    167						p1 = p2;
    168					}
    169					if (type == 1) {
    170						draw = false;
    171						Segment sg = new Segment(type, cl, bs, v);
    172						s.add(sg);
    173						v.clear();
    174					}
    175				}
    176			}
    177		}
    178	}
    179	
    180	/****************************/
    181	/* Control クラス           */
    182	/*      coded by Y.Suganuma */
    183	/****************************/
    184	import java.awt.*;
    185	import javax.swing.*;
    186	import java.awt.event.*;
    187	
    188	class Control extends JPanel
    189	{
    190		Draw dr;   // Draw クラス
    191		JButton type0, type1, color1, color2, line1, line2;
    192						// コンストラクタ
    193		Control(Draw dr)
    194		{
    195			this.dr = dr;
    196								// 背景色の設定
    197			setBackground(new Color(238, 255, 238));
    198								// ボタンの配置
    199			type0 = new JButton("曲線");
    200			type0.addMouseListener(new ClickMouse());
    201			add(type0);
    202	
    203			type1 = new JButton("直線");
    204			type1.addMouseListener(new ClickMouse());
    205			add(type1);
    206	
    207			color1 = new JButton("赤");
    208			color1.setBackground(Color.red);
    209			color1.addMouseListener(new ClickMouse());
    210			add(color1);
    211	
    212			color2 = new JButton("緑");
    213			color2.setBackground(Color.green);
    214			color2.addMouseListener(new ClickMouse());
    215			add(color2);
    216	
    217			line1 = new JButton("細い");
    218			line1.setBackground(Color.yellow);
    219			line1.addMouseListener(new ClickMouse());
    220			add(line1);
    221	
    222			line2 = new JButton("太い");
    223			line2.setBackground(Color.yellow);
    224			line2.addMouseListener(new ClickMouse());
    225			add(line2);
    226		}
    227						// ボタンが押されたときの処理
    228		class ClickMouse extends MouseAdapter {
    229			public void mouseClicked(MouseEvent e)
    230			{
    231				if (e.getSource() == type0)
    232					dr.type = 0;
    233				else if (e.getSource() == type1)
    234					dr.type = 1;
    235				else if (e.getSource() == color1)
    236					dr.cl = Color.red;
    237				else if (e.getSource() == color2)
    238					dr.cl = Color.green;
    239				else if (e.getSource() == line1)
    240					dr.bs = new BasicStroke(1.0f);
    241				else if (e.getSource() == line2)
    242					dr.bs = new BasicStroke(5.0f);
    243			}
    244		}
    245	}
    246	
    247	/****************************/
    248	/* Segment クラス           */
    249	/*      coded by Y.Suganuma */
    250	/****************************/
    251	import java.awt.*;
    252	import javax.swing.*;
    253	import java.util.*;
    254	
    255	class Segment
    256	{
    257		int type;   // 図形の種類(0:自由曲線,1:直線,2:矩形,3:塗りつぶした矩形)
    258		Color cl;   // 描画色
    259		Stroke bs;   // 線のタイプ
    260		ArrayList <Point> v = new ArrayList <Point> ();   // 描画位置データ
    261						// コンストラクタ
    262		Segment(int type, Color cl, Stroke bs, ArrayList <Point> v)
    263		{
    264			this.type = type;
    265			this.cl = cl;
    266			this.bs = bs;
    267			this.v.addAll(v);
    268		}
    269	}
    			
    014 行目~ 015 行目

      MainPanel クラス(クラス定義は 023 行目~ 051 行目,JPanel を継承)のオブジェクトを生成し,JRootPane クラスのオブジェクトに追加している.

    033 行目

      レイアウトマネージャを無効にしている.その結果,コンポーネントを任意の位置に,任意の大きさで配置できるようになる.

    035 行目~ 038 行目

      アプレットの大きさ( 035 行目)から,余白のサイズ( 036 行目)を引き,実際の表示領域を Dimension クラスのオブジェクト size に設定している.

    040 行目~ 044 行目

      MainPanel の右側に,実際に描画を行うパネル( Draw クラス,057 行目~ 178 行目)を追加している.

    046 行目~ 049 行目

      MainPanel の左側に,線の太さ,線の色等を制御するパネル( Control クラス,184 行目~ 245 行目)を追加している.

    082 行目~ 090 行目

      マウスでドラッグしたときの処理であり,自由曲線を描く場合( type = 0 )は,先に述べた例と同様,現在のマウスの位置から Point クラスのオブジェクトを生成し,それを,ArrayList クラスのオブジェクト v に追加している.

    091 行目~ 102 行目

      マウスが移動したときの処理である.自由曲線を描く場合( type = 0 )で,かつ,それまでドラッグしていた場合( draw = true )は,描画を中止し( 096 行目),ArrayList クラスのオブジェクト v に保存されている自由曲線データと線の種類等に関するデータに基づき,Segment クラス( 251 行目~ 269 行目)のオブジェクトを生成し,ArrayList クラスのオブジェクト s に追加している.また,ArrayList クラスのオブジェクト v の内容をクリアしている.

    104 行目~ 121 行目

      マウスをクリックしたときの処理である.直線を描く場合( type = 1 )において,描画中の場合( draw = true )は,終点を ArrayList クラスのオブジェクト v に追加し,再描画している( 110 行目~ 111 行目).また,描画中でない場合( draw = false )は,始点を ArrayList クラスのオブジェクト v に追加し,再描画している( 115 行目~ 118 行目).

    122 行目~ 125 行目

      これらの行は,MouseListener に定義されている関数であり,実際に処理する内容はないが.このような形で定義しておく必要がある.

    131 行目

      Graphics2D クラスのオブジェクトを生成している.Graphics2D クラスは,線の幅等を設定するために必要になる.

    133 行目~ 146 行目

      ArrayList クラスのオブジェクト s に保存されている Segment クラスのオブジェクトに基づき,自由曲線または直線を描画している.

    152 行目~ 159 行目

      type の値が負であることは,117 行目より,直線の始点を指定したことを意味している.ここでは,黒い細い線で,始点に十字を描いている.

    162 行目~ 168 行目

      ArrayList クラスのオブジェクト v に保存された点を結ぶ直線を描いている.

    169 行目~ 174 行目

      ArrayList クラスのオブジェクト v に保存されている直線データと線の種類等に関するデータに基づき,Segment クラスのオブジェクトを生成し,ArrayList クラスのオブジェクト s に追加している.また,ArrayList クラスのオブジェクト v の内容をクリアしている.

    199 行目~ 225 行目

      線の種類,色,太さを変更するために,JButton クラスのオブジェクトを追加している.

    228 行目~ 244 行目

      上で設定した各ボタンがクリックされたときの処理である.クリックされたボタンに従って,Draw クラスのオブジェクトのプロパティ type(線の種類),cl(線の色),または,bs(線の太さ)の値を再設定している.

    251 行目~ 269 行目

      線の種類( type ),線の色( cl ),線の太さ( bs ),線の位置( v )をプロパティとして持つクラスである.

静岡理工科大学 菅沼ホーム Java目次 索引