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
?
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);
Je préférerais la PauseTransition:
PauseTransition wait = new PauseTransition(Duration.seconds(5));
wait.setOnFinished((e) -> {
/*YOUR METHOD*/
wait.playFromStart();
});
wait.play();
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.