java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

タイマーの練習

投稿日:

最終更新日:2018年01月23日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

GUIプログラミングではタイマーを使うことがあると思います。今回はタイマーを使う練習をしてみました。ラベルに数字の10を表示して、0までカウントダウンするプログラムを作ってみました。

ラベルを表示させる

まず、フレームにラベルを表示させることをしました。使うのはJLabelオブジェクトです。コンストラクタJLabel(String text) でテキスト文字列を設定することができます。また、setText(String text)メソッドを使って、再設定することができます。

以下はラベルを表示するだけのプログラムです。

ラベル表示

import javax.swing.JFrame;
import javax.swing.JLabel;

public class MyJFrame extends JFrame {

	private final static int WIDTH  = 300;
	private final static int HEIGHT = 300;

	private JLabel jLabel = new JLabel("テスト");

	public static void main(String[] args) {
		new MyJFrame();
	}

	public MyJFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(WIDTH, HEIGHT);;

		setLabel();

		setVisible(true);
	}

	private void setLabel() {
		add(jLabel);
	}
}

setLabel()メソッドを定義して、その中でラベルをフレームに追加しています。カウントダウンについて記述を追加する想定です。

add()メソッドはContainerクラスで定義されています。JFrameクラスはContainerクラスを親クラスに持っているので、このメソッドが使えます。色々オーバーロードされていますが、基本的には引数がComponentクラスである物を使えばよいと思います。

カウントダウンする

ラベルの初期値は「10」にします。これを0まで順番に表示を減らすようにしていきます。

カウントダウンをするには、タイマーと呼ばれるクラスを使うのですが、今回はjava.utilパッケージに定義されているTimerクラスを使いました。具体的には以下のようにプログラミングしました。

タイマーを使う

import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class MyJFrame extends JFrame {

	private final static int WIDTH  = 300;
	private final static int HEIGHT = 300;

	private JLabel jLabel = new JLabel("10");

	private int count = 0;

	private Timer timer = new java.util.Timer();

	public static void main(String[] args) {
		new MyJFrame();
	}

	public MyJFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(WIDTH, HEIGHT);;

		setLabel();

		setVisible(true);
	}

	private void setLabel() {
		add(jLabel);

		count = 10;
		jLabel.setText(Integer.toString(count));

		timer.schedule(new MyTimeTask(), 5000l, 1000l);
	}

	private class MyTimeTask extends TimerTask {

		@Override
		public void run() {
			if (count > 0) {
				count --;
				jLabel.setText(Integer.toString(count));
			} else {
				timer.cancel();
			}
		}

	}
}

Timerクラスはschedule()メソッドが用意されています。今回は以下のメソッドを使いました。

  • schedule(TimerTask task, long delay, long period)

第一引数にTimerTaskクラスのインスタンスを指定します。このクラスは抽象メソッドrun()を持ちます。このメソッドをオーバーライドして利用します。第二引数は開始のタイミングです。ミリ秒で指定し、その開始時間が指定したミリ秒だけ遅れます。今回は5秒後にタイマーが動くようにしてみました。「5000l」と最後にアルファベット「l」を追加しているのは、long型で指定する必要があるからで、表記法が「xxxl」だからです。

内部クラスにMyTimeTaskクラスを作りました。このクラスはTimerTaskクラスを継承しています。このクラスのインスタンスを上記メソッドの第一引数に指定するという作りにしました。

外部変数にカウントダウン用の変数countを定義して、run()メソッドで1ずつ減らして、ラベルにテキストを再設定しています。countが0になったら、cancel()メソッドを呼び出しています。このメソッドでタイマーを終了することができます。

クリックされたらタスク開始

前述まではフレーム表示と同時にタイマーをスタートさせてましたが、ラベルをクリックしたときにタスクを開始するということもできます。

ソース

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class MyJFrame extends JFrame {

	private final static int WIDTH  = 300;
	private final static int HEIGHT = 300;

	private JLabel jLabel = new JLabel("クリックして下さい。");

	private int count = 0;

	private Timer timer = null;

	public static void main(String[] args) {
		new MyJFrame();
	}

	public MyJFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(WIDTH, HEIGHT);;

		setLabel();

		setVisible(true);
	}

	private void setLabel() {
		add(jLabel);

		jLabel.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
				if (timer == null) {
					count = 10;
					jLabel.setText(Integer.toString(count));
					timer = new java.util.Timer();
					timer.schedule(new MyTimeTask(), 5000l, 1000l);
					// TODO デバッグ用
					System.out.println("タスクスタート");
					System.out.println(LocalDateTime.now());
				}
			}
		});
	}

	private class MyTimeTask extends TimerTask {

		@Override
		public void run() {
			if (count > 0) {
				count --;
				jLabel.setText(Integer.toString(count));
				// TODO デバッグ用
				System.out.println(Integer.toString(count));
				System.out.println(LocalDateTime.now());
			} else {
				timer.cancel();
				timer = null;
				// TODO デバッグ用
				System.out.println("終了");
				System.out.println(LocalDateTime.now());
			}
		}

	}
}

実験的に時刻を表示させてみました。LocalDateTime.now()で時刻が取得できます。Java8の機能です。

クリック時の出力

タスクスタート
2018-01-23T11:28:07.102
9
2018-01-23T11:28:11.837
8
2018-01-23T11:28:12.849
7
2018-01-23T11:28:13.849
6
2018-01-23T11:28:14.861
5
2018-01-23T11:28:15.861
4
2018-01-23T11:28:16.862
3
2018-01-23T11:28:17.862
2
2018-01-23T11:28:18.876
1
2018-01-23T11:28:19.879
0
2018-01-23T11:28:20.879
終了
2018-01-23T11:28:21.880

ほぼ指定通りの間隔でタスクが実行されていることが分かりました。