Tâche d'arrière-plan périodique JavaFX

J'essaie de fonctionner périodiquement dans le thread D'arrière-plan de L'application JavaFX, ce qui modifie certaines propriétés GUI.

Je pense que je sais comment utiliser les classes Task et Service de javafx.concurrent et je ne peux pas comprendre comment exécuter une telle tâche périodique sans utiliser la méthode Thread#sleep(). Ce serait bien si je pouvais utiliser des méthodes Executor de Executors fabricate(Executors.newSingleThreadScheduledExecutor())

J'ai essayé d'exécuter Runnable toutes les 5 secondes, ce qui redémarre javafx.concurrent.Service mais il se bloque immédiatement comme service.restart ou même service.getState() est appelé.

, de Sorte enfin J'utilise Executors.newSingleThreadScheduledExecutor(), ce qui déclenche mon Runnable toutes les 5 sec et que Runnable exécute un autre Runnable utilisation:

Platform.runLater(new Runnable() {
 //here i can modify GUI properties
}

Cela semble très méchant : (y a-t-il une meilleure façon de le faire en utilisant les classes Task ou Service?

49
demandé sur Sergey Grinev 2012-04-01 20:36:59

3 réponses

Vous pouvez utiliser Timeline pour quelle matière:

Timeline fiveSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(5), new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        System.out.println("this is called every 5 seconds on UI thread");
    }
}));
fiveSecondsWonder.setCycleCount(Timeline.INDEFINITE);
fiveSecondsWonder.play();

Pour les processus d'arrière-plan (qui ne font rien à L'interface utilisateur), vous pouvez utiliser old good java.util.Timer:

new Timer().schedule(
    new TimerTask() {

        @Override
        public void run() {
            System.out.println("ping");
        }
    }, 0, 5000);
84
répondu Sergey Grinev 2016-10-14 08:37:33

Je préférerais la PauseTransition:

    PauseTransition wait = new PauseTransition(Duration.seconds(5));
    wait.setOnFinished((e) -> {
        /*YOUR METHOD*/
        wait.playFromStart();
    });
    wait.play();
7
répondu Marcel 2016-01-08 15:57:21

Voici une solution utilisant Java 8 et ReactFX . Dites que vous voulez recalculer périodiquement la valeur de Label.textProperty().

Label label = ...;

EventStreams.ticks(Duration.ofSeconds(5))          // emits periodic ticks
    .supplyCompletionStage(() -> getStatusAsync()) // starts a background task on each tick
    .await()                                       // emits task results, when ready
    .subscribe(label::setText);                    // performs label.setText() for each result

CompletionStage<String> getStatusAsync() {
    return CompletableFuture.supplyAsync(() -> getStatusFromNetwork());
}

String getStatusFromNetwork() {
    // ...
}

Par rapport à la solution de Sergey, vous ne consacrez pas tout le thread à l'obtention du statut du réseau, mais utilisez plutôt le pool de threads partagé pour cela.

5
répondu Tomas Mikula 2014-06-03 22:39:35