JavaFXアプリケーションにカウンターを実装したいのですが。動作はボタンで簡単に制御できます。
- ユーザーが最初にボタンをクリックすると、カウントダウンが開始されます10、9、8、...、0
- カウントダウン中にユーザーがボタンをクリックすると、カウントダウンはキャンセルされます
- 2.の後、ユーザーは10からカウントダウンを再度実行できるようになります。
カウントダウン中に、いくつかの重い数学コンピューティングが処理されます(私のアプリケーションのオーディオ分析で)。
私が正しい方法でそれをしているなら、私のソースコードを見てください。特に、またはで作業を行う必要がありPlatform.runLater
、CountdownController
単純CountdownView
なJavaを使用できますか、それともThread
JavaFX Service
/Task
クラスを使用する必要がありますか?どんな提案でも大歓迎です。
アプリケーションは3つのコンポーネントに分かれています。
CountdownTest
:ステージを作成してJavaFXを開始します)CountdownView
:シングルトン、シンプルなボタンを含み、ボタンイベントをに渡しますCountdownController
CountdownController
:シングルトン、新しいを開始しThread
ます。カウントダウンThread
が実行されると、CountdownView
は更新されて新しいカウントダウン状態が表示され、いくつかの数学が処理されます。
CountdownTest.java
package org.example;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class CountdownTest extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
final Group root = new Group();
final Scene scene = new Scene(root);
root.getChildren().setAll(CountdownView.getInstance());
primaryStage.setScene(scene);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
CountdownController.getInstance().stop();
}
public static void main(String[] args) {
launch(args);
}
}
CountdownView.java
package org.example;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.control.Button;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseEvent;
public final class CountdownView extends Group {
private static final CountdownView instance = new CountdownView();
private Button start;
private CountdownView() {
start = new Button("Start");
start.setTooltip(new Tooltip("click to start countdown"));
start.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
CountdownController.getInstance().onStartClick();
}
});
this.getChildren().setAll(start);
}
public void startCountdown() {
System.out.println("startCountdown");
start.setTooltip(new Tooltip("click to stop countdown"));
}
public void setCountdown(final int countdown) {
System.out.println("setCountdown " + countdown);
start.setText(String.valueOf(countdown));
}
public void reset() {
System.out.println("reset");
start.setText("Start");
start.setTooltip(new Tooltip("click to start countdown"));
}
public static CountdownView getInstance() {
return instance;
}
}
CountdownController.java
package org.example;
import javafx.application.Platform;
public final class CountdownController {
private static final CountdownController instance = new CountdownController();
private Thread countdownThread;
private volatile boolean running = false;
public void onStartClick() {
if (!running) {
countdownThread = new Thread(new Runnable() {
@Override
public void run() {
running = true;
int countdown = 10;
Platform.runLater(new Runnable() {
@Override
public void run() {
CountdownView.getInstance().startCountdown();
CountdownView.getInstance().setCountdown(10);
}
});
final long start = System.currentTimeMillis();
int lastCountdown = countdown;
while (!Thread.interrupted() && countdown > 0) {
countdown = (int) (10 - (System.currentTimeMillis() - start) / 1000);
if (countdown != lastCountdown) {
lastCountdown = countdown;
final int currentCountdown = countdown;
Platform.runLater(new Runnable() {
@Override
public void run() {
CountdownView.getInstance().setCountdown(
currentCountdown);
}
});
}
// Do some heavy computing stuff
for (int i = 0; i < 10000000; i++) {
Math.sin(Math.random());
}
}
running = false;
Platform.runLater(new Runnable() {
@Override
public void run() {
CountdownView.getInstance().reset();
}
});
}
});
countdownThread.start();
} else {
countdownThread.interrupt();
}
}
public void stop() {
if (countdownThread != null) {
System.out.println("stop");
countdownThread.interrupt();
}
}
public static CountdownController getInstance() {
return instance;
}
}