Program Tip

JavaFX 주기적 백그라운드 작업

programtip 2020. 12. 15. 19:46
반응형

JavaFX 주기적 백그라운드 작업


일부 GUI 속성을 수정하는 JavaFX 응용 프로그램 백그라운드 스레드에서 주기적으로 실행하려고합니다.

나는 사용 방법 TaskService수업 방법을 알고 있으며 방법을 사용 javafx.concurrent하지 않고 이러한 주기적 작업을 실행하는 방법을 알 수 없다고 생각합니다 Thread#sleep(). 제조 방법 Executor에서 일부 사용할 수 있으면 좋을 것입니다 Executors( Executors.newSingleThreadScheduledExecutor())

나는 실행하려고 Runnable다시 시작 매 5 초마다, javafx.concurrent.Service그것으로 즉시 중단하지만, service.restart또는 service.getState()호출됩니다.

그래서 마지막으로을 사용합니다 Executors.newSingleThreadScheduledExecutor(). 이것은 Runnable매 5 초마다 Runnable실행 되고 다음을 Runnable사용하여 다른 실행됩니다 .

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

매우 불쾌 해 보입니다 :( Task또는 Service클래스를 사용하는 더 좋은 방법이 있습니까?


해당 문제에 대해 타임 라인을 사용할 수 있습니다.

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();

백그라운드 프로세스 (UI에 아무것도하지 않음)의 경우 old good을 사용할 수 있습니다 java.util.Timer.

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

        @Override
        public void run() {
            System.out.println("ping");
        }
    }, 0, 5000);

PauseTransition을 선호합니다.

    PauseTransition wait = new PauseTransition(Duration.seconds(5));
    wait.setOnFinished((e) -> {
        /*YOUR METHOD*/
        wait.playFromStart();
    });
    wait.play();

다음은 Java 8 및 ReactFX를 사용하는 솔루션 입니다. 의 값을 주기적으로 재 계산하고 싶다고 가정 해보십시오 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() {
    // ...
}

Sergey의 솔루션과 비교할 때 네트워크에서 상태를 가져 오는 데 전체 스레드를 할당하지 않고 대신 공유 스레드 풀을 사용합니다.


당신도 사용할 수 있습니다 ScheduledService. 내가 사용하는 동안 그것을 알아 차리지 후이 대안을 사용하고 TimelinePauseTransition, 내 응용 프로그램에서 일부 UI가 정지 발생, 특히시의 요소와 사용자의 상호 작용 MenuBar(12 자바 FX에). ScheduledService이러한 문제를 사용하면 더 이상 발생하지 않습니다.

class UpdateLabel extends ScheduledService<Void> {

   private Label label;

   public UpdateLabel(Label label){
      this.label = label;
   }

   @Override
   protected Task<Void> createTask(){
      return new Task<Void>(){
         @Override
         protected Void call(){
           Platform.runLater(() -> {
              /* Modify you GUI properties... */
              label.setText(new Random().toString());
           });
           return null;
         }
      }
   }
}

그런 다음 사용하십시오.

class WindowController implements Initializable {

   private @FXML Label randomNumber;

   @Override
   public void initialize(URL u, ResourceBundle res){
      var service = new UpdateLabel(randomNumber);
      service.setPeriod(Duration.seconds(2)); // The interval between executions.
      service.play()
   }
}

ReferenceURL : https://stackoverflow.com/questions/9966136/javafx-periodic-background-task

반응형