GUIアプリ⑦キーイベント

・HelloWorld
・レイアウト
・ダイアログ
・コンポーネント
・描画
・タイマー
・キーイベント(今回)

GUIアプリの連載の続きです。
今回は、キーイベントについてです。
キーボードのキー押下時のイベントを取得して処理します。
キーイベントを使って、簡単なモグラ叩きアプリを作ってみたいと思います。

■Javaソース資源

#ファイル名概要修正/新規
1GuiKeyEvent.javaフレームクラス新規
2TimerEvent.javaタイマーイベントクラス新規

■作成手順

#作成手順備考
1プロジェクト作成プロジェクト名:GuiKeyEvent
2Javaソース(フレームクラス)作成クラス名:GuiKeyEvent
・メイン
・コンストラクタ
・モグラ位置設定
・キープレスド
・アクションパフォームド
3Javaソース(タイマーイベントクラス)作成クラス名:TimerEvent
・コンストラクタ
・ラン

#1 プロジェクト作成

#2 Javaソース(フレームクラス)作成

行数説明
18クラス名:GuiKeyEvent
継承元クラス名:JFrame
インターフェイス名:ActionListener、KeyListner
今回はキーイベントなので、KeyListnerを継承しています。
このインターフェイスを継承するとキーイベントを受け取れるようになります。
20~21finalは定数の意味です。
final int STATE_START=1:スタート状態
final int STATE_STOP=0:ストップ状態
23~27タイマー関連の定義です。
Timer timerMogura (モグラ用タイマー)
TimerEvent timerEventMogura (モグライベント用タイマー)
Timer timerGame (ゲーム用タイマー)
TimerEvent timerEventGame (ゲームイベント用タイマー)
29~36int speed = 700 (モグラスピード初期設定を700ミリ秒)
int moguraPosition = 0(モグラの位置を初期設定を0)
int score = 0 (得点の初期設定を0)
int state = STATE_STOP (状態の初期設定をストップ状態)
38~47モグラ1~9(JLabel)クラスのインスタンスを生成して、ラベルのテキスト表示を「1」~「9」を設定しています。

行数説明
49~50時間ラベル、得点ラベルのインスタンスを生成しています。
53~61メニュー関連のインスタンスを生成しています。
メニューバー(JMenuBar)
メニュー(JMenu)を「メニュー」を設定
メニューアイテム(JMenuItem)を「スタート」、「閉じる」を設定
メニュー(JMenu)を「速さ設定」を設定
メニューアイテム(JMenuItem)を「速い」、「普通」、「遅い」を設定

行数説明
63メソッド名:setMogura(モグラ位置設定)
引数:int moguraNo (モグラ位置)
65メンバ変数のモグラ位置に引数のモグラ位置を設定
67~111モグラ位置に応じて、モグララベル1~9のテキストを設定しています。
モグラ位置の該当のラベルだけ表示されて、その他のラベルは何も表示しません。

行数説明
114メソッド名:setTime(ゲームの経過時間設定)
引数:String time (経過時間)
115経過時間ラベル(labelTime)に、引数の経過時間を設定。
117~125経過時間が30秒かどうか判別しています。
以下のタイマー関連のメンバを停止します。
・モグラタイマー
・モグラタイマーイベント
・ゲームタイマー
・ゲームタイマーイベント
状態を停止に設定。
「ゲーム終了。お疲れ様です。」をメッセージダイアログに表示しています。

行数説明
134@Override (インターフェイスの抽象メソッドを上書きするアノテーション)
135メソッド名:keyPressed(キープレスド)
引数:KeyEvent e(キーイベント)
★今回のメインとなるキーイベントを取得する処理です。
137~138モグラの位置とキーイベントで取得した位置が合っているかかつ状態がゲームスタートしているか判別しています。
139~140得点を加算しています。
得点ラベルのテキストに、「得点:得点値」を表示しています。
※String.valueOf(int)は、int型を文字列に変換しています。

行数説明
150@Override (インターフェイスの抽象メソッドを上書きするアノテーション)
151メソッド名:actionPerformed(アクションパフォームド)
引数:ActionEvent e(アクションイベント)
153アクションイベントが「スタート」メニューか判別しています。
154~156以下タイマー関連のインスタンスを生成しています。
・モグラタイマー
・モグライベント(this, 1)
①引数:this(親コンポーネント)
②引数:TimerEvent.MOGURA_TIMER(タイプ→モグラタイマーイベント)

モグラタイマーを開始しています。
メソッド名:schedule
①引数:timerEventMogura(モグライベント)
②引数:0(開始まで時間)
③引数:speed (タイマーイベントの間隔ミリ秒)
158~160以下タイマー関連のインスタンスを生成しています。
・ゲームタイマー
・ゲームイベント(this, 2)
①引数:this(親コンポーネント)
②引数:TimerEvent.GAME_TIMER(タイプ→ゲームタイマーイベント)

ゲームタイマーを開始しています。
メソッド名:schedule
①引数:timerEventGame(ゲームイベント)
②引数:0(開始まで時間)
③引数:1000 (タイマーイベントの間隔ミリ秒)
162~163得点を初期化して、得点ラベルのテキストに「得点:0」を表示します。
164状態をスタートにします。
166~169アクションイベントが「閉じる」メニューであれば、アプリを終了します。
170~181速さ関連のメニューのイベント処理になります。
「速い」メニュー押下時は、タイマー間隔を500ミリ秒に設定
「普通」メニュー押下時は、タイマー間隔を700ミリ秒に設定
「遅い」メニュー押下時は、タイマー間隔を1000ミリ秒に設定

行数説明
184~187メソッド名:main
コンストラクタを呼ぶのみです。

行数説明
189メソッド名:GuiKeyEvent
コンストラクタになります。
190~205メニュー関連の設定になります。
「メニュー」メニューに、「スタート」、「閉じる」を設定
  「スタート」、「閉じる」メニューをアクションリスナーに登録
「速さ」メニューに、「速い」、「普通」、「遅い」を設定
  「速い」、「普通」、「遅い」メニューをアクションリスナーに登録
メニューバーに、「メニュー」、「速さ」を設定
フレームのメニューバーにメニューバーを設定
207キーアクションリスナーに登録
★今回のキーイベントのメインの処理です。
210フレームのコンテント・ペインのレイアウトをグリッド方式(4行、3列)に設定
211~220モグララベル1~9のフォントを設定しています。
メソッド名:Font
①引数:"MSゴシック"(フォント名)
②引数:Font.BOLD(スタイル)
③引数:100(サイズ)

行数説明
222経過時間ラベルのフォントを設定しています。
メソッド名:Font
①引数:"MSゴシック"(フォント名)
②引数:Font.BOLD(スタイル)
③引数:50(サイズ)
223得点ラベルのフォントを設定しています。
メソッド名:Font
①引数:"MSゴシック"(フォント名)
②引数:Font.BOLD(スタイル)
③引数:20(サイズ)
225~233フレームのコンテント・ペインにモグララベル1~9を配置しています。
235フレームのコンテント・ペインに経過時間ラベルを配置しています。
237フレームのコンテント・ペインに得点ラベルを配置しています。
238~242以下のフレームの設定を行います。
・タイトルを「キーイベントアプリ」に設定
・右上の「×」を押下時アプリを終了するように設定
・サイズを幅300ピクセル、高さ400ピクセルに設定
・画面を表示に設定

#3 Javaソース(タイマーイベントクラス)作成

行数説明
5クラス名:TimerEvent
継承元クラス名:TimerTask
8~9タイマー種別
public final static MOGURA_TIMER = 1(モグラタイマー種別)
public final static GAME_TIMER = 2(ゲームタイマー種別)
※finalは定数
※static 静的変数を意味し、他のクラスからインスタンス生成せずに参照できるようにします。
12GuiKeyEvent guiKeyEvent(親コンポーネント)
14int typeTimer (1:モグラタイマー、2:ゲームタイマー)
16int gameCnt=0(経過時間を初期設定0)

行数説明
18メソッド名:TimerEvent
①引数:GuiKeyEvent object(親コンポーネント)
②引数:int typeTimer (タイマー種別)
19メンバの親コンポーネントに引数の親コンポーネントを設定。
20メンバのタイマー種別に引数のタイマー種別を設定。

行数説明
23@Override (インターフェイスの抽象メソッドを上書きするアノテーション)
24メソッド名:run(ラン)
26タイマー種別がモグラタイマー種別かどうか判別しています。
271~9までのランダムな数字を生成して、モグラNoに設定しています。
28親コンポーネントのモグラ設定メソッドを呼び出しています。
31タイマー種別がゲームタイマー種別かどうか判別しています。
32経過時間が30秒前か判別しています。
33ゲーム経過時間をインクリメントしています。
34親コンポーネントの経過時間設定メソッドを呼び出しています。

■実行

これで準備完了です。実行してみましょう。

メニューの「スタート」メニューをクリックして開始します。

30秒経過で、終了すれば成功です。お疲れ様でした!

☆まとめ☆ 今回は、キーイベントについて学びました。
KeyListenerインターフェイスを継承するとキーイベントを受け取れるようになります。
addKeyListener(this)で、キーリスナーの登録も大切です。
もう7回目なので、GUIアプリだいぶ慣れてきたのではないでしょうか。
次回も宜しくお願いします。

コピーペースト用にソースを記載します。

GuiKeyEvent.java

package app;

import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Timer;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

public class GuiKeyEvent extends JFrame implements ActionListener, KeyListener {

  final int STATE_START = 1;
  final int STATE_STOP = 0;
  
  //タイマー
  Timer timerMogura;
  TimerEvent timerEventMogura;
  Timer timerGame;
  TimerEvent timerEventGame;
  
  //タイマーの速度
  int speed = 700;
  //モグラの位置
  int moguraPosition = 0;
  //得点
  int score = 0;
  //状態
  int state = STATE_STOP;
  
  //モグララベル
  JLabel labelMogura1 = new JLabel("1",JLabel.CENTER);
  JLabel labelMogura2 = new JLabel("2",JLabel.CENTER);
  JLabel labelMogura3 = new JLabel("3",JLabel.CENTER);
  JLabel labelMogura4 = new JLabel("4",JLabel.CENTER);
  JLabel labelMogura5 = new JLabel("5",JLabel.CENTER);
  JLabel labelMogura6 = new JLabel("6",JLabel.CENTER);
  JLabel labelMogura7 = new JLabel("7",JLabel.CENTER);
  JLabel labelMogura8 = new JLabel("8",JLabel.CENTER);
  JLabel labelMogura9 = new JLabel("9",JLabel.CENTER);

  JLabel labelTime = new JLabel("",JLabel.CENTER);
  JLabel labelScore = new JLabel("",JLabel.CENTER);
  

  //メニューのインスタンス
  JMenuBar menuBar = new JMenuBar();
  JMenu menu = new JMenu("メニュー");
  JMenuItem menuStart = new JMenuItem("スタート");
  JMenuItem menuClose = new JMenuItem("閉じる");
  JMenu menuSpeed = new JMenu("速さ設定");
  JMenuItem menuFast = new JMenuItem("速い");
  JMenuItem menuNormal = new JMenuItem("普通");
  JMenuItem menuSlow = new JMenuItem("遅い");
  
  public void setMogura(int moguraNo) {
    //モグラ位置設定
    this.moguraPosition=moguraNo;
    
    if(moguraNo == 1) {
      labelMogura1.setText("1");
    }else {
      labelMogura1.setText("");
    }
    if(moguraNo == 2) {
      labelMogura2.setText("2");
    }else {
      labelMogura2.setText("");
    }
    if(moguraNo == 3) {
      labelMogura3.setText("3");
    }else {
      labelMogura3.setText("");
    }
    if(moguraNo == 4) {
      labelMogura4.setText("4");
    }else {
      labelMogura4.setText("");
    }
    if(moguraNo == 5) {
      labelMogura5.setText("5");
    }else {
      labelMogura5.setText("");
    }  
    if(moguraNo == 6) {
      labelMogura6.setText("6");
    }else {
      labelMogura6.setText("");
    }  
    if(moguraNo == 7) {
      labelMogura7.setText("7");
    }else {
      labelMogura7.setText("");
    }  
    if(moguraNo == 8) {
      labelMogura8.setText("8");
    }else {
      labelMogura8.setText("");
    }
    if(moguraNo == 9) {
      labelMogura9.setText("9");
    }else {
      labelMogura9.setText("");
    }
  }
  
  public void setTime(String time) {
    labelTime.setText(time);
    //ゲーム終了
    if(time.compareTo("30")==0) {
      timerMogura.cancel();
      timerEventMogura.cancel();
      timerGame.cancel();
      timerEventGame.cancel();
      state = STATE_STOP;
      JOptionPane.showMessageDialog(this, "ゲーム終了です。お疲れ様です",
          "information", JOptionPane.INFORMATION_MESSAGE);
    }
  }
  
  @Override
  public void keyTyped(KeyEvent e) {
    // TODO 自動生成されたメソッド・スタブ

  }

  @Override
  public void keyPressed(KeyEvent e) {
    // TODO 自動生成されたメソッド・スタブ
    if(String.valueOf(moguraPosition).compareTo(String.valueOf(e.getKeyChar())) == 0
    && state==STATE_START) {
      score ++;
      labelScore.setText("得点:"+String.valueOf(score));
    }
  }

  @Override
  public void keyReleased(KeyEvent e) {
    // TODO 自動生成されたメソッド・スタブ

  }

  @Override
  public void actionPerformed(ActionEvent e) {
    // TODO 自動生成されたメソッド・スタブ
    if(e.getSource() == menuStart) {
      timerMogura = new Timer();
      timerEventMogura = new TimerEvent(this, TimerEvent.MOGURA_TIMER);
      timerMogura.schedule(timerEventMogura, 0, speed);
      
      timerGame = new Timer();
      timerEventGame = new TimerEvent(this, TimerEvent.GAME_TIMER);
      timerGame.schedule(timerEventGame, 0, 1000);
      //得点初期化
      score = 0;
      labelScore.setText("得点:"+String.valueOf(score));
      state = STATE_START;
    }
    //メニュー閉じるをクリック時
    else if(e.getSource() == menuClose) {
      System.exit(0);
    }
    //速いメニュー押下時
    else if(e.getSource() == menuFast) {
      speed=500;
    }
    //普通メニュー押下時
    else if(e.getSource() == menuNormal) {
      speed=700;
    }
    //遅いメニュー押下時
    else if(e.getSource() == menuSlow) {
      speed=1000;
    }
  }

  public static void main(String[] args) {
    // TODO 自動生成されたメソッド・スタブ
    new GuiKeyEvent();
  }
  
  GuiKeyEvent(){
    //メニューの設定
    menu.add(menuStart);
    menu.add(menuClose);
    menuBar.add(menu);
    menuStart.addActionListener(this);
    menuClose.addActionListener(this);
    
    menuSpeed.add(menuFast);
    menuSpeed.add(menuNormal);
    menuSpeed.add(menuSlow);
    menuBar.add(menuSpeed);
    menuFast.addActionListener(this);
    menuNormal.addActionListener(this);
    menuSlow.addActionListener(this);
    
    setJMenuBar(menuBar);
    //キーリスナー登録
    addKeyListener(this);
    
    //グリッドレイアウト(4行、3列)に設定
    getContentPane().setLayout(new GridLayout(4,3));
    //モグララベル配置
    labelMogura1.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura2.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura3.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura4.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura5.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura6.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura7.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura8.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelMogura9.setFont(new Font("MSゴシック", Font.BOLD, 100));
    
    labelTime.setFont(new Font("MSゴシック", Font.BOLD, 50));
    labelScore.setFont(new Font("MSゴシック", Font.BOLD, 20));

    getContentPane().add(labelMogura7);
    getContentPane().add(labelMogura8);
    getContentPane().add(labelMogura9);
    getContentPane().add(labelMogura4);
    getContentPane().add(labelMogura5);
    getContentPane().add(labelMogura6);
    getContentPane().add(labelMogura1);
    getContentPane().add(labelMogura2);
    getContentPane().add(labelMogura3);
    //時間ラベル配置
    getContentPane().add(labelTime);
    //得点ラベル配置
    getContentPane().add(labelScore);
    //フレーム自身設定
    setTitle("キーイベントアプリ");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(300,400);
    setVisible(true);
  }
  
}

TimerEvent.java

package app;

import java.util.TimerTask;

public class TimerEvent extends TimerTask {

  //タイマー種別
  public final static int MOGURA_TIMER = 1;
  public final static int GAME_TIMER = 2;
  
  //親コンポーネント
  GuiKeyEvent guiKeyEvent;
  //タイマー種別
  int typeTimer;
  //経過時間
  int gameCnt = 0;
  
  TimerEvent(GuiKeyEvent object, int typeTimer){
    this.guiKeyEvent = object;
    this.typeTimer = typeTimer;
  }
  
  @Override
  public void run() {
    // TODO 自動生成されたメソッド・スタブ
    if(typeTimer == MOGURA_TIMER) {
      int moguraNo = (int)Math.ceil(Math.random() * 9);
      //モグラの設定
      guiKeyEvent.setMogura(moguraNo);
    }
    else if(typeTimer == GAME_TIMER) {
      if(gameCnt < 30) {
        gameCnt ++;
        guiKeyEvent.setTime(String.valueOf(gameCnt));
      
      }
    }
    
  }
}

Follow me!