0

JavaFXアプリケーションにカウンターを実装したいのですが。動作はボタンで簡単に制御できます。

  1. ユーザーが最初にボタンをクリックすると、カウントダウンが開始されます10、9、8、...、0
  2. カウントダウン中にユーザーがボタンをクリックすると、カウントダウンはキャンセルされます
  3. 2.の後、ユーザーは10からカウントダウンを再度実行できるようになります。

カウントダウン中に、いくつかの重い数学コンピューティングが処理されます(私のアプリケーションのオーディオ分析で)。

私が正しい方法でそれをしているなら、私のソースコードを見てください。特に、またはで作業を行う必要がありPlatform.runLaterCountdownController単純CountdownViewなJavaを使用できますか、それともThreadJavaFX Service/Taskクラスを使用する必要がありますか?どんな提案でも大歓迎です。

アプリケーションは3つのコンポーネントに分かれています。

  1. CountdownTest:ステージを作成してJavaFXを開始します)
  2. CountdownView:シングルトン、シンプルなボタンを含み、ボタンイベントをに渡しますCountdownController
  3. 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;
    }
}
4

1 に答える 1

1

汗をかきすぎないでください。タスククラスとサービスクラスは、エグゼキュータ上に構築されたユーティリティの一部にすぎません。エグゼキュータが提供するものが必要ない場合は、追加の作業になります。

コントローラーを使用して実行するスレッドを決定するのは正しいと思います。ビューには、コンポーネントとコントローラーの間でメッセージをルーティングするのに十分なものがあります。

于 2012-12-02T18:20:01.077 に答える