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

イベント処理

  1. マウスクリック
      まず最初に,MouseAdapter クラスを使用して,マウスでクリックした場合の処理方法について説明します.以下に示すプログラム( Test.java )は,マウスクリックに対する処理例です.上図における矩形内部の円をクリックすると,イベントevent )が発生し,mouseClicked が呼び出されます(円を左から右,又は,右から左に移動).
    001	import java.awt.*;
    002	import java.awt.event.*;
    003	import javax.swing.*;
    004	
    005	public class Test {
    006		public static void main (String[] args)
    007		{
    008			Win win = new Win("マウスクリック");
    009		}
    010	}
    011	
    012	class Win extends JFrame
    013	{
    014		/******************/
    015		/* コンストラクタ */
    016		/******************/
    017		Win(String name)
    018		{
    019						// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    020			super(name);
    021						// Windowの大きさ
    022			setSize(310, 200);   // +40, +70
    023						// ContentPane の取得と MainPanel の追加
    024			MainPanel pn = new MainPanel();   // MainPanel オブジェクトの生成
    025			getContentPane().add(pn);   // MainPanel オブジェクトを ContentPane に追加
    026			pn.setSize(270, 130);
    027						// ウィンドウを表示
    028			setVisible(true);
    029						// イベントアダプタ
    030			addWindowListener(new WinEnd());
    031		}
    032	
    033		/******************************/
    034		/* 上,左,下,右の余白の設定 */
    035		/******************************/
    036		public Insets getInsets()
    037		{
    038			return new Insets(50, 20, 20, 20);
    039		}
    040	
    041		/************/
    042		/* 終了処理 */
    043		/************/
    044		class WinEnd extends WindowAdapter
    045		{
    046			public void windowClosing(WindowEvent e) {
    047				System.exit(0);
    048			}
    049		}
    050	}
    051	
    052	class MainPanel extends JPanel
    053	{
    054		int x = 30, y = 25;
    055	
    056		MainPanel()
    057		{
    058			setBackground(new Color(238, 255, 238));   // 背景色の設定
    059			addMouseListener(new ClickMouse());   // MouseListenerの追加
    060		}
    061						// 描画
    062		public void paintComponent(Graphics g)
    063		{
    064			super.paintComponent(g);   // 親クラスの描画
    065								// Graphics2Dの取得
    066			Graphics2D g2 = (Graphics2D)g;
    067								// 線幅が5ピクセルの矩形
    068			g2.setStroke(new BasicStroke(5.0f));
    069			g2.draw(new Rectangle(20, 15, 100, 100));
    070			g2.draw(new Rectangle(150, 15, 100, 100));
    071								// 塗りつぶされた円
    072			g.setColor(Color.green);
    073			g.fillOval(x, y, 80, 80);
    074		}
    075	
    076		/******************************/
    077		/* クリック押されたときの処理 */
    078		/******************************/
    079		class ClickMouse extends MouseAdapter {
    080			public void mouseClicked(MouseEvent e)
    081			{
    082				int x1 = e.getX();
    083				int y1 = e.getY();
    084	
    085				if (x1 < 125) {
    086					x1 -= 70;
    087					y1 -= 65;
    088					double r = Math.sqrt(x1 * x1 + y1 * y1);
    089					if (r <= 40.0) {
    090						x = 160;
    091						repaint();
    092					}
    093				}
    094				else {
    095					x1 -= 200;
    096					y1 -= 65;
    097					double r = Math.sqrt(x1 * x1 + y1 * y1);
    098					if (r <= 40.0) {
    099						x = 30;
    100						repaint();
    101					}
    102				}
    103			}
    104		}
    105	}
    			
    054 行目

      円を描く位置(円に接する四角形の左上頂点の座標.従って,円の中心の座標は,これらの値に円の半径である 40 を加えた位置になる)を記憶する変数です.描画方法は,基本的に,「図形の描画」と同じですが,円を描いた位置を他のクラスやメソッドで参照する必要があるため,円の位置に関する変数をここ(メソッドの外側)で定義しています.

    059 行目

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

      イベントの送出は,リスナのインタフェース(または,イベントアダプタ)に定義されているイベント応答メソッド(ハンドラメソッド)の内1つを呼び出し,引数としてイベントソースが生成したイベントオブジェクトを渡すといった方法で行われます.イベントリスナはインタフェースとして提供されています.これは,各イベントの処理がアプリケーションによって異なる場合が多いからです.しかし,インタフェースを実装する際には,インタフェースに定義されているすべてのメソッド(ハンドラメソッド)を実装しない限り,抽象クラスとなり,インスタンスを生成できなくなります.実際にすべてのメソッドを必要とする場合は問題ありませんが,この例に示すように,一部のメソッドだけを使用したい場合においても,必要としないメソッドまですべて定義しなければならず,余分な作業が必要になります.

      059 行目では,画面上でマウスがクリックされたときの処理を行うため,MouseListener を追加しています.この結果,画面上でマウスをクリックすると,080 行目~ 103 行目の mouseClicked メソッドが実行されます.

      他のイベントにおいても同様ですが,マウスクリックイベントを処理するには 2 つの方法が存在します.一つは,MouseAdapter クラスを継承する方法です.しかし,MainPanel クラスは,既に JPanel クラスを継承しており,多重継承(複数のクラスを同時に継承すること)が出来ない Java では不可能です.そこで,このプログラムのように,クラス内に ClickMouse クラスを定義し,そのクラスに MouseAdapter クラスを継承させて,処理を行っています( 079 行目).今まで説明しなかった Window を閉じるための処理( Window イベント,030 行目,044 行目~ 049 行目)も,この方法で行っています.

      他の一つは,MainPanel クラスに,MouseListener インターフェースを継承させる方法です.次の節で述べるドラッグに対しては,この方法を使用しています.インターフェースを利用した場合では,WinEnd クラスや ClickMouse クラスのようなクラス内クラスを定義する必要はありませんが,MouseAdapter クラスなどのイベントアダプタに定義されているすべてのメソッドを再定義してやる必要があります.この例の場合,マウスがクリックされたときの処理である mouseClicked メソッドだけが必要であるにもかかわらず,mouseEnteredmouseExitedmousePressedmousePressed の定義も必要になります(内容は空で良い).

    082 行目~ 083 行目

      マウスがクリックされた位置を表します.

    085 行目~ 093 行目

      円が,左の矩形内に存在するときの処理です.088 行目において,Math クラスのメソッド sqrt を利用して,マウスがクリックされた位置から円の中心までの距離を求めています.089 行目~ 091 行目では,その値が円の半径 40 以下である場合(円をクリックした場合)は,円を描画する位置を変更し,再描画しています.

    094 行目~ 102 行目

      円が,右の矩形内に存在するときの処理であり,上と同様の処理を行っています.

  2. ドラッグ
      ドラッグも,MouseMotionAdapter クラスを利用することによって簡単に実現できます.この例では,円にマウスカーソルを合わせてドラッグすると,円を移動することができます.上図は,初期状態において左側矩形内にあった円を,少し移動した状態を表しています.
    001	import java.awt.*;
    002	import java.awt.event.*;
    003	import javax.swing.*;
    004	
    005	public class Test {
    006		public static void main (String[] args)
    007		{
    008			Win win = new Win("ドラッグ");
    009		}
    010	}
    011	
    012	class Win extends JFrame
    013	{
    014		/******************/
    015		/* コンストラクタ */
    016		/******************/
    017		Win(String name)
    018		{
    019						// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    020			super(name);
    021						// Windowの大きさ
    022			setSize(310, 200);   // +40, +70
    023						// ContentPane の取得と MainPanel の追加
    024			MainPanel pn = new MainPanel();   // MainPanel オブジェクトの生成
    025			getContentPane().add(pn);   // MainPanel オブジェクトを ContentPane に追加
    026			pn.setSize(270, 130);
    027						// ウィンドウを表示
    028			setVisible(true);
    029						// イベントアダプタ
    030			addWindowListener(new WinEnd());
    031		}
    032	
    033		/******************************/
    034		/* 上,左,下,右の余白の設定 */
    035		/******************************/
    036		public Insets getInsets()
    037		{
    038			return new Insets(50, 20, 20, 20);
    039		}
    040	
    041		/************/
    042		/* 終了処理 */
    043		/************/
    044		class WinEnd extends WindowAdapter
    045		{
    046			public void windowClosing(WindowEvent e) {
    047				System.exit(0);
    048			}
    049		}
    050	}
    051	
    052	class MainPanel extends JPanel implements MouseMotionListener
    053	{
    054		int x = 30, y = 25, xb = 30, yb = 25, x0 = 0, y0 = 0;
    055		boolean drag = false;
    056	
    057		MainPanel()
    058		{
    059			setBackground(new Color(238, 255, 238));   // 背景色の設定
    060			addMouseMotionListener(this);   // MouseMotionListenerの追加
    061		}
    062						// 描画
    063		public void paintComponent(Graphics g)
    064		{
    065			super.paintComponent(g);   // 親クラスの描画
    066								// Graphics2Dの取得
    067			Graphics2D g2 = (Graphics2D)g;
    068								// 線幅が5ピクセルの矩形
    069			g2.setStroke(new BasicStroke(5.0f));
    070			g2.draw(new Rectangle(20, 15, 100, 100));
    071			g2.draw(new Rectangle(150, 15, 100, 100));
    072								// 塗りつぶされた円
    073			g.setColor(Color.green);
    074			g.fillOval(x, y, 80, 80);
    075		}
    076	
    077		/******************************/
    078		/* マウスが移動したときの処理 */
    079		/******************************/
    080		public void mouseDragged(MouseEvent e)
    081		{
    082			if (!drag) {
    083				double x1 = e.getX() - (x + 40);
    084				double y1 = e.getY() - (y + 40);
    085				double r = Math.sqrt(x1 * x1 + y1 * y1);
    086				if (r <= 40.0) {
    087					x0 = e.getX();
    088					y0 = e.getY();
    089					drag = true;
    090				}
    091			}
    092			else {
    093				x = xb + (e.getX() - x0);
    094				y = yb + (e.getY() - y0);
    095				repaint();
    096			}
    097		}
    098		public void mouseMoved(MouseEvent e)
    099		{
    100			if (drag) {
    101				drag = false;
    102				xb = x;
    103				yb = y;
    104			}
    105		}
    106	}
    			
    052 行目

      MouseMotionListener インターフェースを継承しています.

    054 行目

      x 及び y は円の現在位置,xb 及び yb はドラッグを終了したときの円の位置(当初は,x,y の値と同じ),また,x0 及び y0 はドラッグを開始したときのマウスの位置を表します.

    055 行目

      この変数は,ドラッグ中は true に,そうでないときは false に設定されます.

    060 行目

      MouseMotionListener を追加しています( addMouseMotionListener ).

    080 行目~ 097 行目

      ドラッグ中の処理です.変数 drag が false の場合は(ドラッグ中でない状態である場合は),マウスの位置と円の中心間の距離を調べ,それが円の半径内であった場合は,マウスの位置を x0 及び y0 に記憶すると共に,変数 drag を true に設定します( 086 行目~ 090 行目).また,変数 drag が既に true であった場合は,現在の円の位置を再計算し,再描画します( 092 行目~ 096 行目).

    098 行目~ 105 行目

      マウスがボタンを押されずに移動している場合に対する処理です.変数 drag が true であった場合は(ドラッグを終了した場合は),現在の円の位置を xb 及び yb に記憶すると共に,変数 drag を false に設定します.

  3. キーイベント

      次に,KeyAdapter クラスを使用した操作について説明します.この例においては,n キーを押すと,円の位置が変化します.なお,このプログラムを実行したときの初期画面は,上に示した 2 つの例と同じですので省略します.
    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("キーイベント");
    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		int x = 30, y = 25;
    55	
    56		MainPanel()
    57		{
    58			setBackground(new Color(238, 255, 238));   // 背景色の設定
    59			addKeyListener(new Key());   // KeyListenerの追加
    60		}
    61						// 描画
    62		public void paintComponent(Graphics g)
    63		{
    64			super.paintComponent(g);   // 親クラスの描画
    65								// Graphics2Dの取得
    66			Graphics2D g2 = (Graphics2D)g;
    67								// 線幅が5ピクセルの矩形
    68			g2.setStroke(new BasicStroke(5.0f));
    69			g2.draw(new Rectangle(20, 15, 100, 100));
    70			g2.draw(new Rectangle(150, 15, 100, 100));
    71								// 塗りつぶされた円
    72			g.setColor(Color.green);
    73			g.fillOval(x, y, 80, 80);
    74		}
    75	
    76		/************************************************/
    77		/* キーイベントを受け付けるようにする           */
    78		/* (フォーカスを受けることができるようにする) */
    79		/************************************************/
    80		public boolean isFocusable() { return true; }
    81	
    82		/****************************/
    83		/* キーが押されたときの処理 */
    84		/****************************/
    85		class Key extends KeyAdapter {
    86			public void keyPressed(KeyEvent e)
    87			{
    88				if (e.getKeyChar() == 'n') {
    89					if (x < 125)
    90						x = 160;
    91					else
    92						x = 30;
    93					repaint();
    94				}
    95			}
    96		}
    97	}
    			
    59 行目

      KeyListener を追加しています.この例では,マウスクリックの場合と同様,クラス内クラスを利用し,そのクラスに KeyAdapter クラスを継承させています( 85 行目).

    80 行目

      キーイベントを有効にするための処理です.

    86 行目~ 95 行目

      キーが押されたときの処理です.キーの種類を判別し,「 n 」キーであれば,円の移動を行っています.

  4. もう一つの例

      この例では,円をマウスでクリックしても,n キーを押しても,円が移動するようにしています.このプログラムを実行したときの初期画面も,上に示した 3 つの例と同じですので省略します.
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Test {
    	public static void main (String[] args)
    	{
    		Win win = new Win("マウスイベント+キーイベント");
    	}
    }
    
    class Win extends JFrame
    {
    	/******************/
    	/* コンストラクタ */
    	/******************/
    	Win(String name)
    	{
    					// JFrameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    		super(name);
    					// Windowの大きさ
    		setSize(310, 200);   // +40, +70
    					// ContentPane の取得と MainPanel の追加
    		MainPanel pn = new MainPanel();   // MainPanel オブジェクトの生成
    		getContentPane().add(pn);   // MainPanel オブジェクトを ContentPane に追加
    		pn.setSize(270, 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
    {
    	int x = 30, y = 25;
    
    	MainPanel()
    	{
    		setBackground(new Color(238, 255, 238));   // 背景色の設定
    		addMouseListener(new ClickMouse());   // MouseListenerの追加
    		addKeyListener(new Key());   // KeyListenerの追加
    	}
    					// 描画
    	public void paintComponent(Graphics g)
    	{
    		super.paintComponent(g);   // 親クラスの描画
    							// Graphics2Dの取得
    		Graphics2D g2 = (Graphics2D)g;
    							// 線幅が5ピクセルの矩形
    		g2.setStroke(new BasicStroke(5.0f));
    		g2.draw(new Rectangle(20, 15, 100, 100));
    		g2.draw(new Rectangle(150, 15, 100, 100));
    							// 塗りつぶされた円
    		g.setColor(Color.green);
    		g.fillOval(x, y, 80, 80);
    	}
    
    	/******************************/
    	/* クリック押されたときの処理 */
    	/******************************/
    	class ClickMouse extends MouseAdapter {
    		public void mouseClicked(MouseEvent e)
    		{
    			int x1 = e.getX();
    			int y1 = e.getY();
    
    			if (x1 < 125) {
    				x1 -= 70;
    				y1 -= 65;
    				double r = Math.sqrt(x1 * x1 + y1 * y1);
    				if (r <= 40.0) {
    					x = 160;
    					repaint();
    				}
    			}
    			else {
    				x1 -= 200;
    				y1 -= 65;
    				double r = Math.sqrt(x1 * x1 + y1 * y1);
    				if (r <= 40.0) {
    					x = 30;
    					repaint();
    				}
    			}
    		}
    	}
    
    	/************************************************/
    	/* キーイベントを受け付けるようにする           */
    	/* (フォーカスを受けることができるようにする) */
    	/************************************************/
    	public boolean isFocusable() { return true; }
    
    	/****************************/
    	/* キーが押されたときの処理 */
    	/****************************/
    	class Key extends KeyAdapter {
    		public void keyPressed(KeyEvent e)
    		{
    			if (e.getKeyChar() == 'n') {
    				if (x < 125)
    					x = 160;
    				else
    					x = 30;
    				repaint();
    			}
    		}
    	}
    }
    			

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