↓↓クリックして頂けると励みになります。
【29 | アニメーション描画】 << 【ホーム】 >> 【31 | 乱数】
Javaのイベント処理は「イベント駆動型」と呼ばれる処理で行います。
イベント駆動型とはオブジェクトに何らかのイベントが発生した場合はあらかじめ定義された事柄を実行する方法で、イベントが発生したかどうかはアプリケーションで判断してそれに対応する処理を行います。
こうすることによりプログラマーは「イベントを待ち受ける」というようなプログラムを記述する必要が無くなり、「何が起こったときに何をする」という処理を記述することに専念できます。
Javaでのイベント処理はイベント駆動型の処理を複数のオブジェクトを組み合わせて行っています。
「発生源のオブジェクト」->「イベントのオブジェクト」->「リスナのオブジェクト」
例えばキャンバス上でマウスクリックされたとします。
この場合「発生源はCanvas」->「イベントはMouseEvent」->「MouseEventを受け取って処理するリスナはMouseListener」というようになります。
まずはイベント処理(クローズボタンで終了)を行うフレームを作成するプログラムを作ってみましょう。
Visual Studio Codeで以下のサンプルプログラムを作成して下さい。
新規作成 【MyFrame.java】
import java.awt.*; import java.awt.event.*; public class MyFrame extends Frame implements WindowListener { /**コンストラクタ*/ public MyFrame(String frameName) { //フレームのタイトルを設定 setTitle(frameName); //スレームで発生したイベント通知用として登録 addWindowListener(this); } /**ウィンドウをクローズした時の処理*/ public void windowClosing(WindowEvent evt) { dispose(); //ウィンドウを閉じる } /*ウィンドウクローズ後の処理*/ public void windowClosed(WindowEvent evt) { System.exit(0); //プログラム終了 } /**その他のウィンドウ処理*/ public void windowDeiconified(WindowEvent evt) { } public void windowIconified(WindowEvent evt) { } public void windowOpened(WindowEvent evt) { } public void windowActivated(WindowEvent evt) { } public void windowDeactivated(WindowEvent evt) { } /**main()メソッド*/ public static void main(String[] args) { MyFrame frame = new MyFrame("MyFrameTest"); frame.setSize(200,100); frame.setVisible(true); } }
リスナでは通知されたイベント情報から「○○のアクションがあった場合」というようにアクションに対応したメソッドが設定されていますので、プログラムではこれらのメソッドの実装を行う必要があります。
リスナはインターフェイスですのでimplementsする必要があります。
またリスナはオブジェクトに登録することで利用可能になりますから、implementsしていても登録しなければオブジェクトへのイベントがリスナに通知されることはありません。
登録には「add○○Listener()
」を用います。
import java.awt.event.*; //AWTのイベントはjava.awt.eventパッケージで定義 public class Test implements MouseListener { /**マウスがクリックされたときの処理*/ public void mouseClicked(MouseEvent evt) { //処理 } /**その他のマウス処理(リスナを利用する場合、処理はなくても空で実装する)*/ public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } public void mousePressed(MouseEvent evt) { } public void mouseReleased(MouseEvent evt) { } public static void main(String[] args) { Canvas c = new Canvas(); c.addMouseListener(this); //イベント通知用のリスナをCanvasに登録 } }
イベントに対応する処理を行う方法としては、このほかにAdapterクラスと呼ばれるものを利用する方法があります(MouseListenerインターフェイスに対応するのはMouseAdapterクラス)。
Adapterはリスナを利用する際必ず実装しなければいけなかったメソッドをあらかじめ「空で定義」してあるクラスというだけです。
ですからAdapterクラスを継承(extends)したクラスでは「空定義メソッド」は記述する必要はありません。
AWTでのイベントのクラス構成は以下のようになっています(今回使用するイベントは、WindowEvent・KeyEvent・MouseEvent)。
java.lang.Object +--java.util.EventObject +--java.awt.AWTEvent | +--java.awt.event.ActionEvent +--java.awt.event.AdjustmentEvent +--java.awt.event.ItemEvent +--java.awt.event.TextEvent +--java.awt.event.HierarchyEvent +--java.awt.event.InputMethodEvent +--java.awt.event.InvocationEvent +--java.awt.event.ComponentEvent | +--java.awt.event.ContainerEvent +--java.awt.event.FocusEvent +--java.awt.event.PaintEvent +--java.awt.event.WindowEvent +--java.awt.event.InputEvent | +--java.awt.event.KeyEvent +--java.awt.event.MouseEvent | +--java.awt.event.MouseWheelEvent
上記イベントの発生が通知されるリスナ(あるいはAdapter)と実装すべきメソッドは以下のようになっています。
なお親インターフェイスはjava.util.EventListenerです。
インターフェイス名 | 対応するAdapter | 受け取るイベントとその働き | 実装すべきメソッド |
---|---|---|---|
ActionListener | なし | ActionEvent ボタンのクリックなど | actionPerformed() |
AdjustmentListener | なし | AdjustmentEvent 位置などの調整 | adjustmentValueChanged() |
ItemListener | なし | ItemEvent チェックボックスの項目選択など | itemStateChanged() |
TextListener | なし | TextEvent テキストの値が変更 | textValueChanged() |
InputMethodListener | なし | InputMethodEvent インプットメソッドを利用して変換されるテキスト | inputMethodTextChanged() caretPositionChanged() |
HierarchyListener | なし | HierarchyEvent 断層変更 | hierarchyChanged() |
HierarchyBoundsListener | HierarchyBoundsAdapter | HierarchyEvent 移動およびサイズ変更された上位クラスのイベント | ancestorMoved() ancestorResized() |
ComponentListener | ComponentAdapter | ComponentEvent コンポーネントの移動やサイズ変更など | componentResized() componentMoved() componentShown() componentHidden() |
ContainerListener | ContainerAdapter | ContainerEvent コンテナの追加や削除など | componentAdded() componentRemoved() |
FoucusListener | FoucusAdapter | FocusEvent コンポーネントの入力フォーカスの取得など | focusGained() focusLost() |
WindowListener | WindowAdapter | WindowEvent ウィンドウの状態変化 | windowOpened() windowClosing() windowClosed() windowIconified() windowDeiconified() windowActivated() windowDeactivated() |
WindowFoucusListener | なし | WindowEvent ウィンドウの状態変化 | windowGainedFocus() windowLostFocus() |
WindowStateListener | なし | WindowEvent ウィンドウの状態変化 | windowStateChanged() |
KeyListener | KeyAdapter | KeyEvent キー入力が発生 | keyTyped() keyPressed() keyReleased() |
MouseListener | MouseAdapter | MouseEvent マウスのアクション | mouseClicked() mousePressed() mouseReleased() mouseEntered() mouseExited() |
MouseMotionListener | MouseMotionAdapter | MouseEvent マウスのアクション | mouseDragged() mouseMoved() |
MouseWheelListener | なし | MouseEvent マウスのアクション | mouseWheelMoved() |
リスナを登録するには先に述べたようにオブジェクト(今回はコンポーネント)に対して「
add○○Listener(リスナ)
」を用います。今回使用するのは、
WindowListener
、MouseListener
、KeyListener
ですから、以下のようになります(各リスナはimplementsされているとします)。
Frame f = new Frame(); Canvas c = new Canvas(); f.addWindowListener(this); //WindowListenerを登録 c.addMouseListener(this); //MouseListenerを登録 c.addKeyListener(this); //KeyListenerを登録
引数には実行処理を定義したリスナを指定します(addWindowListenerならWindowListenerオブジェクト)。
今回は自分のクラスにimplementsされているのでthisとしています。
WindowListenerは発生したWindowEventをもとに以下のメソッドを実行します。
メソッド(引数はWindowEvent) | 起こったマウスのアクション |
---|---|
windowOpened() | 最初に可視になったとき |
windowClosing() | 閉じようとしたとき |
windowClosed() | 閉じられたとき |
windowIconified() | アイコンになったとき |
windowDeiconified() | アイコンから復帰したとき |
windowActivated() | アクティブウィンドウになったとき |
windowDeactivated() | アクティブウィンドウでなくなったとき |
リスナはインターフェイスですので、必ず実装しなければいけないメソッドがあります。
メソッドの実装忘れや、メソッド名を間違えるとコンパイルエラーが出ます。
public class MyFrame extends Frame implements WindowListener {
Frameクラスを継承し、WindowListenerを実装しています。
サンプルプログラム「MyFrame.java」をコンパイルして実行してみましょう。
「クローズボタンで終了」できるフレームができます。
大きさは「200,100」で背景は白です。
~/Desktop/Programming/JP $ javac MyFrame.java ~/Desktop/Programming/JP $ java MyFrame
キャンバスでキーボードとマウスの入力を受け付けるサンプルプログラムを作成してみましょう。
このプログラムは、上で作成した「MyFrame.java」を利用しています。
新規作成 【EventTest1.java】
import java.awt.*; import java.awt.event.*; public class EventTest1 extends Canvas implements KeyListener, MouseListener, Runnable { private final int MAX_IMAGE = 7; private final int WIDTH = 500; private final int HEIGHT = 400; private Image[] image = new Image[MAX_IMAGE]; private MediaTracker tracker; //ダブルバッファリング(オフスクリーン・バッファ用)変数 private Graphics offg; private Image offImage; private int x =0; //画像の座標 private int y = 100; private int w; //画像の幅と高さ private int h; private int imageNum = 0; //利用する画像 private int imageCount = 1; //画像の枚数のカウント制御 private int moveCount = 5; //移動距離カウント制御 private int mx, my; //マウスの座標取得用 /**コンストラクタ*/ public EventTest1() { setSize(WIDTH, HEIGHT); setBackground(Color.black); Toolkit tk = Toolkit.getDefaultToolkit(); tracker = new MediaTracker(this); //キャラクターイメージの作成 for (int i=0; i<MAX_IMAGE; i++) { image[i] = tk.getImage("char" + i + ".gif"); tracker.addImage(image[i], i); } //全イメージのダウンロードが終わるまで待つ try { tracker.waitForAll(); } catch (InterruptedException e) { System.err.println("tracker error"); } //キャラクターイメージの幅と高さと取得 w = image[0].getWidth(this); h = image[0].getHeight(this); //Canvasで発生したイベントを通知 addKeyListener(this); addMouseListener(this); } /**メインの処理(スレッド処理)*/ public void run() { while (true) { //永久に繰り返し try { Thread.sleep(100); //100ミリ秒(0.1秒)スリープ } catch (InterruptedException ex) { System.err.println(ex); } repaint(); } } /**再描写が必要な場合の処理*/ public void update(Graphics g) { //キャラクタ、障害物の消去(全画面消去) //オフスクリーン・バッファへの描き込み。実際にはまだ見えない offg.setColor(Color.black); offg.fillRect(0, 0, WIDTH, HEIGHT); //口を開けるアニメか、閉じるアニメかを設定 if(imageNum >= (MAX_IMAGE-1)) { imageCount = -1; } else if (imageNum <= 0) { imageCount = 1; } imageNum+=imageCount; //オフスクリーン・バッファへの描き込み。実際にはまだ見えない offg.drawImage(image[imageNum], x, y, this); //イメージとマウスがクリックされたときの座標を描画 offg.setColor(Color.yellow); offg.drawString("x=" + x + ", y=" + y, 10, 10); offg.drawString("mx=" + mx + ", my=" + my, 10, 30); //オフスクリーン・バッファへに描かれたものを画面に表示 g.drawImage(offImage, 0, 0, this); } /**キャンバスで描写の必要があるときに呼ばれるメソッド*/ public void paint(Graphics g) { //オフスクリーンバッファの領域がない場合は作成 if (offg == null) { //キャンバスと同じ大きさの仮想画面を生成 offImage = createImage(getSize().width, getSize().height); //offImageから仮想画面描画用のグラフィックスコンテキストを取得 offg = offImage.getGraphics(); } //イメージと文字列の描画 g.drawImage(image[imageNum], x, y, this); g.setColor(Color.yellow); g.drawString("x=" + x + ", y=" + y, 10, 10); g.drawString("mx=" + mx + ", my=" + my, 10, 30); } /**キーが押されたときの処理*/ public void keyPressed(KeyEvent evt) { int key = evt.getKeyCode(); //移動範囲内だけで移動 if (key == evt.VK_LEFT && x > 0) { x -= moveCount; } else if (key == evt.VK_RIGHT && x < WIDTH-w) { x += moveCount; } } /**その他のキー処理*/ public void keyReleased(KeyEvent evt) { } public void keyTyped(KeyEvent evt) { } /**マウスがクリックされたときの処理*/ public void mouseClicked(MouseEvent evt) { mx = evt.getX(); my = evt.getY(); } /**その他のマウス処理*/ public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } public void mousePressed(MouseEvent evt) { } public void mouseReleased(MouseEvent evt) { } /**main()メソッド*/ public static void main(String[] args) { EventTest1 canvas = new EventTest1(); //自作のクラスMyFrameを利用 MyFrame frame = new MyFrame("EventTest1"); frame.add(canvas); frame.pack(); frame.setVisible(true); //スレッドを生成して開始(runメソッドの呼び出し) new Thread(canvas).start(); } }
このプログラムを実行するには画像ファイルが必要です。
char0.gif〜char6.gifをプログラムを保存するのと同じフォルダ(ディレクトリ)に保存してください。
[char0.gif]
[char1.gif]
[char2.gif]
[char3.gif]
[char4.gif]
[char5.gif]
[char6.gif]
MouseListenerは発生したMouseEventをもとに以下のメソッドを実行します。
メソッド(引数はMouseEvent) | 起こったマウスのアクション |
---|---|
mouseClicked() | クリックしたとき |
mousePressed() | 押したとき |
mouseReleased() | 離したとき |
mouseEntered() | コンポーネントにマウスが入ったとき |
mouseExited() | コンポーネントからマウスが出たとき |
MouseEventのオブジェクト.get○○
」で取り出せます。例えば「
getX()
」「getY()
」はクリックされたときのマウスカーソルの座標を取得できます。KeyListenerは発生したKeyEventをもとに以下のメソッドを実行します。
メソッド(引数はKeyEvent) | 起こったキー入力のアクション |
---|---|
keyTyped() | タイプしたとき |
keyPressed() | 押したとき |
keyReleased() | 離したとき |
KeyEventのオブジェクト.get○○
」で取り出せます。例えば、低レベルなイベントの
keyPressed()
とkeyReleased()
では、「getKeyCode()
」で入力されたキーの情報を取り出せます。このときのキー情報は「VK_UP(カーソル移動キーの上矢印キー)」などの仮想キーコードです。
キーコードの詳細は、APIドキュメントのKeyEventクラスを参照して下さい。
public class EventTest1 extends Canvas implements KeyListener, MouseListener, Runnable {
Canvasクラスを継承し、KeyListenerとMouseListener、Runnableの3つのインターフェイスを実装しています。
ではサンプルプログラムを実行してみましょう。
「クローズボタンで終了」できるフレームができます。
大きさは「500,400」で背景は黒です。
char0.gif〜char6.gifの画像がアニメーションで動きます。
キーボードの←
→
キーでその画像が移動します。
移動した位置が画面左上に表示されます(x,y)
。
フレーム内をマウスでクリックすると、クリックした位置が画面左上に表示されます(mx,my)
。
~/Desktop/Programming/JP $ javac EventTest1.java ~/Desktop/Programming/JP $ java EventTest1
【29 | アニメーション描画】 << 【ホーム】 >> 【31 | 乱数】
↓↓クリックして頂けると励みになります。