GUIアプリ⑥タイマー

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

GUIアプリの連載の続きです。
今回は、タイマーについてです。
タイマーは、定期的に処理したいときに使用します。
タイマーを使って、簡単なスロットアプリを作ってみたいと思います。

■Javaソース資源

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

■作成手順

#作成手順備考
1プロジェクトの作成プロジェクト名:GuiTimerEvent
2Javaソース(フレームクラス)作成・メイン
・コンストラクタ
・(オーバライド)アクションリスナー
・スロット(ラベル)設定
・当たり判定
3Javaソース(タイマーイベントクラス)作成・コンストラクタ
・(オーバライド)ラン

#1 プロジェクトの作成

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

行数説明
17クラス名:GuiTimerEvent(GUIタイマーイベント)
継承元クラス名:JFrame(フレーム)
インターフェイス名:ActionLister(アクションリスナー)
20~22スロットの状態を定数としています。finalは定数のときに使用します。
定数 int型:BEFORE_STRT(0)
定数 int型:RUN(1)
定数 int型:STOP(2)
24~29今回スロットを3つ使用するので、3つタイマーを用意します。
タイマー1~3(Timer)クラスを定義しています。
タイマーイベント1~3(TimerEvent)クラスを定義しています。
31タイマーの速度として、初期値200ミリ秒(millisecond)を設定しています。
※ミリ秒は1000分の1秒の意味です。
33~35スロット1~3の状態を開始前(BEFORE_START)に設定しています。

行数説明
38~45メニュー関連のインスタンスを生成します。
「メニュー」(JMenu)に、「スタート」、「閉じる」(JMenuItem)を設定します。
「速さ設定」(JMenu)に、「速い」、「普通」、「遅い」(JMenuItem)を設定します。
48~50ラベル1~3(JLabel)クラスの初期値「7」に設定してインスタンスを生成しています。
52~54ストップボタン1~3(JButton)クラスのインスタンスを生成しています。

行数説明
56このメソッドは、タイマーイベントクラスのイベントから呼ぶためにpublic(公開)で定義しています。
メソッド名:setSlot(スロット設定)
①引数:int slotlNo(スロットNo)
②引数:String cnt(スロットに表示させる数字)
57~65ラベルNoに応じたスロット1~3(ラベル)のテキストに数字(cnt)を設定する。
行数説明
68~69アノテーション:@Override(インターフェイスの抽象メソッドをオーバライド)
メソッド名:actionPerfomed(アクションパフォームド)
引数:ActionEvent e(アクションイベント)
71アクションイベントが「メニュースタート」かどうか判別しています。
72~77今回スロット3つ使用するため、タイマーも3つ用意します。
タイマー1~3(Timer)クラスのインスタンスを生成しています。
タイマーイベント1~3(TimerEvent)クラスのインスタンスを生成しています。
78~80タイマー1~3クラスでスケジュール(schedule)メソッドを呼んでいます。
①引数:timerEvent1~3(タイマーイベント)
②引数:0(開始までの時間ミリ秒)
③引数:speed(タイマーイベントの間隔ミリ秒)
81~83スロット1~3を実行中(RUN)に設定しています。
86アクションイベントが「メニュー閉じる」かどうか判別しています。
87アプリを終了します。

行数説明
90アクションイベントがストップボタン1かつスロット1が実行中かどうか判別しています。
91~94タイマー1(Timer)クラスを停止します。
タイマーイベント1(TimerEvent)クラスを停止します。
スロット1の状態を停止(STOP)に設定しています。
当たり判定(hitJudge)メソッドを呼んでいます。
97アクションイベントがストップボタン2かつスロット2が実行中かどうか判別しています。
98~101タイマー2(Timer)クラスを停止します。
タイマーイベント2(TimerEvent)クラスを停止します。
スロット2の状態を停止(STOP)に設定しています。
当たり判定(hitJudge)メソッドを呼んでいます。
104アクションイベントがストップボタン3かつスロット3が実行中かどうか判別しています。
105~108タイマー3(Timer)クラスを停止します。
タイマーイベント3(TimerEvent)クラスを停止します。
スロット3の状態を停止(STOP)に設定しています。
当たり判定(hitJudge)メソッドを呼んでいます。

行数説明
111アクションイベントが「速い」メニューかどうか判別しています。
112タイマーイベントの間隔を100ミリ秒に設定しています。
115アクションイベントが「普通」メニューかどうか判別しています。
116タイマーイベントの間隔を200ミリ秒に設定しています。
119アクションイベントが「遅い」メニューかどうか判別しています。
120タイマーイベントの間隔を300ミリ秒に設定しています。

行数説明
124メソッド名:hitJudge(当たり判定)
125スロット1~3が停止(STOP)状態になっているか判別しています。
126~127スロット1~3のテキストのカウンタが等しいか判別しています。
128~129メッセージダイアログを表示します。
①引数:this(親コンポーネント)
②引数:「当たりです!おめでとうございます!」(メッセージ)
③引数:information(タイトルバー)
④引数:JOptionPane.INFORMATION_MESSAGE(アイコン)

行数説明
134~137メインメソッドになります。
コンストラクタを呼ぶのみです。

行数説明
139コンストラクタになります。
141~145「メニュー」に、「スタート」、「閉じる」を設定しています。
メニューバーに「メニュー」を追加しています。
「スタート」メニュー(menuStart)をアクションリスナーに登録しています。
「閉じる」メニュー(menuClose)をアクションリスナーに登録しています。
147~153「速さ設定」メニューに「速い」、「普通」、「遅い」を設定しています。
メニューバーに「速さ設定」を追加しています。
「速い」メニュー(menuFast)をアクションリスナーに登録しています。
「普通」メニュー(menuNormal)をアクションリスナーに登録しています。
「遅い」メニュー(menuSlow)をアクションリスナーに登録しています。
155フレーム自身のメニューバーにメニューバーを設定しています。

行数説明
158フレーム自身のコンテント・ペインのレイアウトをグリッドレイアウト2行、3列に設定しています。
160~162スロット1~3(ラベル)のフォントを設定しています。
①引数:"MSゴシック"(フォント名)
②引数:Font.BOLD(スタイル)
③引数:100(サイズ)
163~165フレーム自身のコンテント・ペインに、スロット1~3(ラベル)を配置しています。
167~169フレーム自身のコンテント・ペインに、ストップボタン1~3を配置しています。
170~172ストップボタン1~3をアクションリスナーに登録しています。
175~178フレーム自身を以下の設定をしています。
タイルトルバー:タイマーアプリ
フレームの右上の「×」ボタン押下時に閉じるようにします。
フレームサイズを幅300ピクセル、高さ300ピクセルに設定しています。
フレームを表示します。

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

行数説明
5クラス名:TimerEvent
継承元クラス名:TimerTask
7スロットカウンタ(slotCnt)に初期値7を設定してます。
8スロットNo(slotNo)をメンバとして定義しています。
9親コンポーネントをメンバとして定義しています。
11コンストラクタ
①引数:GuiTimerEvent object(親コンポーネント)
②引数:int slotNo(スロットNo)
12引数の親コンポーネントをメンバ(guiTimerEvent)に設定しています。
13引数のスロットNoをメンバ(slotNo)に設定しています。

行数説明
16~17アノテーション:@Override(抽象メソッドのオーバライド)
メソッド名:run(実行)
19~24スロットカウンタ(slotCnt)が9未満の場合、インクリメントします。
そうでなければ、0を設定します。
25親コンポーネントクラスのスロット設定メソッドを呼びます。
メソッド名:setSlot
①引数:slotNo(スロットNo)
②引数:String.valueOf(slotCnt) (スロットカウンタを文字列型に変換しています)

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

■実行

起動画面が表示します。

メニューから「スタート」を選択するとスロットが回転します。回転後、ストップボタンを押すと止まります。

スロットが3つ揃うと当たりメッセージが表示します。
この当たりメッセージが出れば成功です。
お疲れ様でした。

☆まとめ☆ 今回は、タイマーについて学びました。
タイマーを使うと、定期的に処理することができます。
タイマーイベントで、親側のコンポーネントを編集したいことはよくあると思ます。
その場合、タイマークラスのインスタンス生成の時に親側のコンポーネントを渡してあげる必要があります。
次回も宜しくお願いします。

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

GuiTimerEvent.java

package app;

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

import javax.swing.JButton;
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 GuiTimerEvent extends JFrame implements ActionListener {

  //スロットの状態
  final int BEFORE_START = 0;
  final int RUN = 1;
  final int STOP = 2;
  //タイマー
  Timer timer1;
  Timer timer2;
  Timer timer3;
  TimerEvent timerEvent1;
  TimerEvent timerEvent2;
  TimerEvent timerEvent3;
  //タイマーの速度
  int speed = 200;
  //スロットの状態
  int slot1 = BEFORE_START;
  int slot2 = BEFORE_START;
  int slot3 = BEFORE_START;
  
  //メニューのインスタンス
  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("遅い");
  
  //スロットラベル
  JLabel labelSlot1 = new JLabel("7",JLabel.CENTER);
  JLabel labelSlot2 = new JLabel("7",JLabel.CENTER);
  JLabel labelSlot3 = new JLabel("7",JLabel.CENTER);
  //ストップボタン
  JButton timerStopBtn1 = new JButton("ストップ");
  JButton timerStopBtn2 = new JButton("ストップ");
  JButton timerStopBtn3 = new JButton("ストップ");
  
  public void setSlot(int slotNo, String cnt) {
    if(slotNo==1) {
      labelSlot1.setText(cnt);
    }
    else if(slotNo==2) {
      labelSlot2.setText(cnt);
    }
    else if(slotNo==3) {
      labelSlot3.setText(cnt);
    }
  }
  
  @Override
  public void actionPerformed(ActionEvent e) {
    // TODO 自動生成されたメソッド・スタブ
    if(e.getSource() == menuStart) {
      timer1 = new Timer();
      timer2 = new Timer();
      timer3 = new Timer();
      timerEvent1 = new TimerEvent(this,1);
      timerEvent2 = new TimerEvent(this,2);
      timerEvent3 = new TimerEvent(this,3);
      timer1.schedule(timerEvent1, 0, speed);
      timer2.schedule(timerEvent2, 0, speed);
      timer3.schedule(timerEvent3, 0, speed);
      slot1 = RUN;
      slot2 = RUN;
      slot3 = RUN;
    }
    //メニュー閉じるをクリック時
    else if(e.getSource() == menuClose) {
      System.exit(0);
    }
    //ストップボタン1押下時
    else if(e.getSource() == timerStopBtn1 && slot1 == RUN) {
      timer1.cancel();
      timerEvent1.cancel();
      slot1 = STOP;
      hitJudge();
    }
    //ストップボタン2押下時
    else if(e.getSource() == timerStopBtn2 && slot2 == RUN) {
      timer2.cancel();
      timerEvent2.cancel();
      slot2 = STOP;
      hitJudge();
    }
    //ストップボタン3押下時
    else if(e.getSource() == timerStopBtn3 && slot3 == RUN) {
      timer3.cancel();
      timerEvent3.cancel();
      slot3 = STOP;
      hitJudge();
    }
    //速いメニュー押下時
    else if(e.getSource() == menuFast) {
      speed=100;
    }
    //普通メニュー押下時
    else if(e.getSource() == menuNormal) {
      speed=200;
    }
    //遅いメニュー押下時
    else if(e.getSource() == menuSlow) {
      speed=300;
    }
  }
  //当たり判定
  public void hitJudge(){
    if(slot1 == STOP && slot2 == STOP && slot3 == STOP) {
      if(Integer.valueOf(labelSlot1.getText()) == Integer.valueOf(labelSlot2.getText())
      && Integer.valueOf(labelSlot2.getText()) == Integer.valueOf(labelSlot3.getText())) {
        JOptionPane.showMessageDialog(this, "当たりです!おめでとうございます!",
            "information", JOptionPane.INFORMATION_MESSAGE);
      }
    }
  }

  public static void main(String[] args) {
    // TODO 自動生成されたメソッド・スタブ
    new GuiTimerEvent();
  }
  
  GuiTimerEvent(){
    //メニューの設定
    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);
    
    //グリッドレイアウト(3行、3列)に設定
    getContentPane().setLayout(new GridLayout(2,3));
    //スロットラベル配置
    labelSlot1.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelSlot2.setFont(new Font("MSゴシック", Font.BOLD, 100));
    labelSlot3.setFont(new Font("MSゴシック", Font.BOLD, 100));
    getContentPane().add(labelSlot1);
    getContentPane().add(labelSlot2);
    getContentPane().add(labelSlot3);
    //ストップボタン配置
    getContentPane().add(timerStopBtn1);
    getContentPane().add(timerStopBtn2);
    getContentPane().add(timerStopBtn3);
    timerStopBtn1.addActionListener(this);
    timerStopBtn2.addActionListener(this);
    timerStopBtn3.addActionListener(this);
    
    //フレーム自身設定
    setTitle("タイマーアプリ");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(300,300);
    setVisible(true);
  }

}

TimerEvent.java

package app;

import java.util.TimerTask;

public class TimerEvent extends TimerTask {

  int slotCnt = 7;
  int slotNo;
  GuiTimerEvent guiTimerEvent;
  
  TimerEvent(GuiTimerEvent object, int slotNo){
    this.guiTimerEvent = object;
    this.slotNo = slotNo;
  }
  
  @Override
  public void run() {
    // TODO 自動生成されたメソッド・スタブ
    if(slotCnt < 9) {
      slotCnt++;
    }else {
      slotCnt=0;
    }
    //スロット設定
    guiTimerEvent.setSlot(slotNo, String.valueOf(slotCnt));
  }

}

Follow me!