概要
以前投稿した「JavaFX でストップウォッチを作る」のコメントで @shiracamus さんからカップラーメンタイマーのリクエストを受けましたので、作ってみました。
必要な機能
- 3分、4分、5分のボタン
- 押すとカウントダウンが始まる
- 0でチャルメラ
- 音が鳴らない人のためにポップアップウィンドウ表示
- 停止ボタン
スクリーンショット
起動直後です。クローズボタンだけ赤くしました。
大きな数字のボタンを押すとタイマーにセットされます。いずれも分単位です。
3-5分しかできないのはカップラーメンの多様性にそぐわないので、好きな時間を分単位で入力できるTextFieldを用意してあります。10分どん兵衛 (リンク先は NAVERまとめ の記事です) を試したい方もこれで安心ですね。
▶のボタンを押すとカウントダウンが始まります。カウントダウン中は■ボタンに変化し、このボタンを押せば一時中断が可能です。
0になると音声とダイアログで通知します。なお、音声ファイルはWindowsのデフォルトを使用しています。音声ファイルが存在しない場合はダイアログだけ表示されます。
注意
Dialog を使用しているため、Java SE 8u40以前の環境では動作しません。
実装
jp.toastkid.gui.jfx.noodle_timer パッケージにすべてのクラスを置いてあります。各クラスのポイントを説明します。
Main.java
Application をスタートさせるクラスです。
Windows の場合、 JavaFX のタスクアイコンは下記のやり方で設定可能です。
final Image image = new Image(getClass().getClassLoader().getResourceAsStream(PATH_TO_ICON));
stage.getIcons().add(image);
Controller.java
UIからの入力に対し操作を実行するクラスです。
Notifier.java
通知を実行するクラスです。具体的にはダイアログの表示と音声ファイルの再生を実施します。下記の通り、 Builder を使って初期化します。
notifier = new Notifier.Builder().setPathToWav(Resource.PATH_TO_WAV)
.setTitle("時間です!")
.setMessage("ラーメンができました!!!!!")
.build();
アイコン差し替え
ダイアログはアイコンを差し替えてみました。
final Image image = new Image(getClass().getClassLoader().getResourceAsStream("ramen.png"));
final Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
stage.getIcons().add(image);
alert.setGraphic(new ImageView(image));
Stopwatch.java
カウントダウンタイマーを拡張で実装しました。
コールバック設定機能
Start/ Stop 時にボタンの表示変更をしたかったので、コールバックを設定できるようにしてあります。
Controllerクラスから下記の通り設定してあります。
timer.setOnStart( () -> {ctrl.setText("■");});
timer.setOnStop( () -> {ctrl.setText("▶");});
自作の Control に独自の property を追加
コンストラクタの引数に NamedArg アノテーションを追加します。
この場合、 FXML で additional という属性名を指定してやることで値を設定できます。
public Stopwatch(@NamedArg("isCountDown") final boolean isCountDown) {
<Stopwatch fx:id="timer" prefHeight="400.0" prefWidth="525.0" isCountDown="true" />
NumberTextField.java
数値だけを受け付ける機能は TextField を拡張して用意しました。 replaceText と replaceSelection メソッドを Override し、validate というバリデーションメソッドを通して残った値を入力値とするものです。これを応用すれば、逆に文字列だけを受け付ける TextField 等も作れます。
@Override
public void replaceText(final int start, final int end, final String text) {
if (validate(text)){
super.replaceText(start, end, text);
}
}
@Override
public void replaceSelection(final String text) {
if (validate(text)) {
super.replaceSelection(text);
}
}
private boolean validate(final String text) {
return text.matches("[0-9]*");
}
Resource.java
アイコンと音声ファイルの置き場所を定数で保持しているクラスです。
改良点
- JFoenix を使って Material Design 化
- 秒単位でのタイマー設定
- チャルメラ音ほか任意の効果音を設定可能にする
- 残り時間に合わせて色を変える
- デザイン修正