JavaFXで時間管理タイマーを作る [まとめ]
JavaFXで時間管理タイマーを作る [時刻編]
Java日付時刻APIメモ(Hishidama's Java8 Date and Time API Memo)
このサイトを参考に時刻関連の実装を行う
仕様変更
- らぼりだ時刻は普段使われないので現在時刻を表示する。
コード(追加部分)
private LocalDateTime dt; private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd HH:mm:ss"); private Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), //時間経過をトリガにするのはTimelineクラスを使う new EventHandler<ActionEvent>() { public void handle(ActionEvent actionEvent) { //ここに書いた処理がDuration.seconds(1)で示した感覚で実行される dt = LocalDateTime.now(); nowTime.setText(dt.format(dtf)); } } ) ); public void mainButtonClick(ActionEvent actionEvent) { if (mainTimer.getStatus()){ //タイマーが動作中のクリック nowTimeLabel.setText("らぼりだ: "); dt = LocalDateTime.now(); nowTime.setText(dt.format(dtf)); }else { //タイマーが動作していない dt = LocalDateTime.now(); inDate.setText(dt.format(dtf)); nowTimeLabel.setText("現在時刻: "); } }
成果物
一応完成ということにします
JavaFXで時間管理タイマーを作る [ボタン編]
ボタンを押したら実際に動作するところまで作ります。
コード
Controller クラス
import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.util.Duration; import javafx.scene.control.Label; import java.net.URL; import java.util.ResourceBundle; import static javafx.animation.Animation.INDEFINITE; public class Controller implements Initializable { private LabT mainTimer = new LabT(); private LabT allTimer = new LabT(); private LabT researchTimer = new LabT(); private LabT restTimer = new LabT(); private LabT otherTimer = new LabT(); private Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), //時間経過をトリガにするのはTimelineクラスを使う new EventHandler<ActionEvent>() { public void handle(ActionEvent actionEvent) { //ここに書いた処理がDuration.seconds(1)で示した感覚で実行される mainTimer.timeCount(); allTimer.timeCount(); researchTimer.timeCount(); restTimer.timeCount(); otherTimer.timeCount(); mainTimerLabel.setText(mainTimer.formatPrint()); allTimerLabel.setText(allTimer.formatPrint()); childTimerLabel1.setText(researchTimer.formatPrint()); childTimerLabel2.setText(restTimer.formatPrint()); childTimerLabel3.setText(otherTimer.formatPrint()); } } ) ); @FXML private Label mainTimerLabel; @FXML private Label allTimerLabel; @FXML public Label childTimerLabel1; @FXML public Label childTimerLabel2; @FXML public Label childTimerLabel3; @FXML public Button mainButton; @FXML public Label statusLabel; public Controller() { } public void button1Click(ActionEvent actionEvent) { researchTimer.active(); restTimer.inactive(); otherTimer.inactive(); mainTimer.reset(); mainTimerLabel.setText(mainTimer.formatPrint()); //0に戻ったことを表示 statusLabel.setText("研究中"); } public void button2Click(ActionEvent actionEvent) { researchTimer.inactive(); restTimer.active(); otherTimer.inactive(); mainTimer.reset(); mainTimerLabel.setText(mainTimer.formatPrint()); statusLabel.setText("休憩中"); } public void button3Click(ActionEvent actionEvent) { researchTimer.inactive(); restTimer.inactive(); otherTimer.active(); mainTimer.reset(); mainTimerLabel.setText(mainTimer.formatPrint()); statusLabel.setText("その他動作中"); } public void mainButtonClick(ActionEvent actionEvent) { if (mainTimer.getStatus()){ //タイマーが動作中のクリック researchTimer.inactive(); //タイマーがstop時、全部非アクティブ前提 restTimer.inactive(); otherTimer.inactive(); allTimer.inactive(); mainTimer.inactive(); timeline.stop(); mainButton.setText("らぼいん"); statusLabel.setText("らぼりだ中"); }else { //タイマーが動作していない mainButton.setText("らぼりだ"); researchTimer.reset(); restTimer.reset(); otherTimer.reset(); allTimer.reset(); mainTimer.reset(); mainTimerLabel.setText(mainTimer.formatPrint()); //0に戻ったことを表示 allTimerLabel.setText(allTimer.formatPrint()); childTimerLabel1.setText(researchTimer.formatPrint()); childTimerLabel2.setText(restTimer.formatPrint()); childTimerLabel3.setText(otherTimer.formatPrint()); mainTimer.active(); allTimer.active(); button1Click(null); //らぼいん初回は研究中とする timeline.setCycleCount(INDEFINITE); //何回繰り返すか指定する timeline.play(); } } @Override public void initialize(URL url, ResourceBundle resourceBundle) { mainTimerLabel.setText(mainTimer.formatPrint()); allTimerLabel.setText(allTimer.formatPrint()); childTimerLabel1.setText(researchTimer.formatPrint()); childTimerLabel2.setText(restTimer.formatPrint()); childTimerLabel3.setText(otherTimer.formatPrint()); mainButton.setText("らぼいん"); statusLabel.setText("らぼりだ中"); } }
fxml
<?import javafx.geometry.Insets?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <GridPane fx:controller="Controller" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"> <Label text="らぼいん: " GridPane.rowIndex="0" GridPane.columnIndex="0"/> <Label fx:id="inDate" text="dummy" GridPane.rowIndex="0" GridPane.columnIndex="1"/> <Label text="らぼりだ: " GridPane.rowIndex="0" GridPane.columnIndex="2"/> <Label fx:id="outDate" text="dummy" GridPane.rowIndex="0" GridPane.columnIndex="3"/> <Label text="らぼ時間" GridPane.rowIndex="1" GridPane.columnIndex="0"/> <Label fx:id="allTimerLabel" GridPane.rowIndex="2" GridPane.columnIndex="1"/> <Label text="研究時間: " GridPane.rowIndex="3" GridPane.columnIndex="0"/> <Label fx:id="childTimerLabel1" GridPane.rowIndex="3" GridPane.columnIndex="1"/> <Label text="休憩時間: " GridPane.rowIndex="4" GridPane.columnIndex="0"/> <Label fx:id="childTimerLabel2" GridPane.rowIndex="4" GridPane.columnIndex="1"/> <Label text="その他時間: " GridPane.rowIndex="5" GridPane.columnIndex="0"/> <Label fx:id="childTimerLabel3" GridPane.rowIndex="5" GridPane.columnIndex="1"/> <Label text="状態: " GridPane.rowIndex="6" GridPane.columnIndex="0"/> <Label fx:id="statusLabel" text="dummy" GridPane.rowIndex="6" GridPane.columnIndex="1"/> <Label fx:id="mainTimerLabel" GridPane.rowIndex="7" GridPane.columnIndex="1"/> <Button fx:id="mainButton" GridPane.rowIndex="8" GridPane.columnIndex="0" onAction="#mainButtonClick"/> <Button fx:id="childButton1" text="研究" GridPane.rowIndex="8" GridPane.columnIndex="1" onAction="#button1Click"/> <Button fx:id="childButton2" text="休憩" GridPane.rowIndex="8" GridPane.columnIndex="2" onAction="#button2Click"/> <Button fx:id="childButton3" text="その他" GridPane.rowIndex="8" GridPane.columnIndex="3" onAction="#button3Click"/> </GridPane>
解説
前回からの変更点
- コンストラクタに処理を書いていたのを対応したボタンとイニシャライザに割り当てた
- ボタンにonActionを追加
ボタンのクリックと関数について
- fxmlで作成したボタンをクリックするとonActionに対応した関数が実行される
- なのでボタンクリック時に実行したい処理を対応した関数内に書いていく
- 引数には何が入るのかは勉強不足により不明
mainButtonClick
- トグル的な動作をさせたいのでif文で動作を切り替えるようにしている
- ボタンと対応させた関数も普通に呼び出すことができる
initializeのoverride
- initializeをオーバーライドすることで起動時に行われる処理を新たに記述することができる
- 使用にはInitializableの継承が必要
成果画面
次回は日付部分実装したい
JavaFXで時間管理タイマーを作る [タイマー編]
時間経過に応じてカウントがインクリメントされて表示されるためのコア部分を作成する
コード(抜粋)
private LabT mainTimer = new LabT(); private LabT allTimer = new LabT(); private LabT researchTimer = new LabT(); private LabT restTimer = new LabT(); private LabT otherTimer = new LabT(); @FXML private Label mainTimerLabel; //略 private Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), //時間経過をトリガにするのはTimelineクラスを使う new EventHandler<ActionEvent>() { public void handle(ActionEvent actionEvent) { //ここのブロック内に書いた処理がDuration.seconds()で示した感覚で実行される。今回は1秒 mainTimer.timeCount(); //一括でタイマーのカウントアップを命令する allTimer.timeCount(); researchTimer.timeCount(); restTimer.timeCount(); otherTimer.timeCount(); mainTimerLabel.setText(mainTimer.formatPrint()); //表示の更新 allTimerLabel.setText(allTimer.formatPrint()); childTimerLabel1.setText(researchTimer.formatPrint()); childTimerLabel2.setText(restTimer.formatPrint()); childTimerLabel3.setText(otherTimer.formatPrint()); } } )); public Controller() { //コンストラクタ mainTimer.active(); //カウントアップしたいタイマーのみをアクティブにする allTimer.active(); researchTimer.active(); timeline.setCycleCount(INDEFINITE); //何回繰り返すか指定する。INDEFINITEで制限なし timeline.play(); //動作開始 }
解説
JavaFXで時間管理タイマーを作る [見た目編]
前回の記事
fxmlファイルをいじってどういった見た目になるか規定していきます。
コード
- GridPaneに配置すれば格子状に配列されるらしい
- 要素は揃ったけど見た目的にはダサいのでなんとかしたい
- テキストは適当においた(参考: らぼったあ | としつーる )
<?import javafx.geometry.Insets?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <GridPane fx:controller="Controller" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"> <Label text="らぼいん: " GridPane.rowIndex="0" GridPane.columnIndex="0"/> <Label fx:id="inDate" text="dummy" GridPane.rowIndex="0" GridPane.columnIndex="1"/> <Label text="らぼりだ: " GridPane.rowIndex="0" GridPane.columnIndex="2"/> <Label fx:id="outDate" text="dummy" GridPane.rowIndex="0" GridPane.columnIndex="3"/> <Label text="らぼ時間" GridPane.rowIndex="1" GridPane.columnIndex="0"/> <Label fx:id="allTimerLabel" GridPane.rowIndex="2" GridPane.columnIndex="1"/> <Label text="研究時間: " GridPane.rowIndex="3" GridPane.columnIndex="0"/> <Label fx:id="childTimerLabel1" GridPane.rowIndex="3" GridPane.columnIndex="1"/> <Label text="休憩時間: " GridPane.rowIndex="4" GridPane.columnIndex="0"/> <Label fx:id="childTimerLabel2" GridPane.rowIndex="4" GridPane.columnIndex="1"/> <Label text="その他時間: " GridPane.rowIndex="5" GridPane.columnIndex="0"/> <Label fx:id="childTimerLabel3" GridPane.rowIndex="5" GridPane.columnIndex="1"/> <Label text="状態: " GridPane.rowIndex="6" GridPane.columnIndex="0"/> <Label fx:id="statusLabel" text="dummy" GridPane.rowIndex="6" GridPane.columnIndex="1"/> <Label fx:id="mainTimerLabel" GridPane.rowIndex="7" GridPane.columnIndex="1"/> <Button fx:id="mainButton" text="らぼいん/らぼりだ" GridPane.rowIndex="8" GridPane.columnIndex="0"/> <Button fx:id="childButton1" text="研究" GridPane.rowIndex="8" GridPane.columnIndex="1"/> <Button fx:id="childButton2" text="休憩" GridPane.rowIndex="8" GridPane.columnIndex="2"/> <Button fx:id="childButton3" text="その他" GridPane.rowIndex="8" GridPane.columnIndex="3"/> </GridPane>
結果
次回
JavaFXで時間管理タイマーを作る [設計編]
JavaとJavaFXとタイピング*1の練習で実用的かつかんたんなアプリケーションを作成したい。
画面設計
入室時間 退室時間
総時間(おおきめ)
総研究時間
総休憩時間
総その他時間
現在の状態(研究/休憩/その他)
現在の状態時間(おおきめ)
入室/退室ボタン 研究ボタン 休憩ボタン その他ボタン
クラス設計
- 経過時間と状態を持つクラスを作成
- 状態によって毎秒カウントアップするか判別
実装
class LabT {
private long time = 0;
private boolean status = false;
void timeCount(){
if (status) time++;
}
void reset(){
time = 0;
}
long getTime(){
return time;
}
boolean getStatus() {
return status;
}
void active(){
status = true;
}
void inactive(){
status = false;
}
String formatPrint(){
return String.format("%02d:%02d:%02d", time/3600%60, time/60%60, time%60);
}
}
続き
追記
なんだこれ
桁がおかしい
修正しておきました
元コード
String formatPrint(){
return String.format("%02d:%02d:%02d", time/3600, time/60, time%60);
}