2014-11-23 4 views
1

Я хотел бы иметь индикатор выполнения, который обновляется внутри блока onAction. По какой-то причине в следующем коде индикатор выполнения не обновляется до тех пор, пока он не выйдет из блока onAction. Я не получаю никакого прогресса в течение девяти секунд, а затем 90%. System.out печатает просто отлично.ProgressBar в Javafx не обновляется в блоке onAction

package net.snortum.play; 

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.text.Text; 
import javafx.stage.Stage; 

public class ProgressBarTester extends Application { 

    public static void main(String[] args) { 
     launch(ProgressBarTester.class, args); 
    } 

    @Override 
    public void start(final Stage stage) throws Exception { 
     final GridPane grid = new GridPane(); 
     grid.setAlignment(Pos.CENTER); 
     grid.setHgap(10); 
     grid.setVgap(10); 
     grid.setPadding(new Insets(25, 25, 25, 25)); 

     final Text title = new Text("Test Progress Bar"); 
     int col = 0, row = 0, colSpan = 2, rowSpan = 1; 
     grid.add(title, col, row, colSpan, rowSpan); 

     col = 0; 
     row++; 
     grid.add(new Label("Progress:"), col, row); 
     col = 1; 
     final ProgressBar progress = new ProgressBar(0.0); 
     grid.add(progress, col, row); 

     final HBox hbox = new HBox(); 
     hbox.setAlignment(Pos.BASELINE_RIGHT); 
     final Button submit = new Button("Go"); 
     hbox.getChildren().add(submit); 
     col = 1; 
     row++; 
     grid.add(hbox, col, row); 

     submit.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       double size = 10.0; 
       for (double i = 0.0; i < size; i++){ 
        progress.setProgress(i/size); 
        System.out.printf("Complete: %02.2f%n", i * 10); 

        try { 
         Thread.sleep(1000); 
        } catch(InterruptedException ex) { 
         Thread.currentThread().interrupt(); 
        } 
       } 
      } 

     }); 

     final Scene scene = new Scene(grid); 
     stage.setScene(scene); 
     stage.setTitle("Test Progress Bar"); 
     stage.show(); 
    } 

} 

ответ

10

Длинная форма точного ответа tomsomtom в:

Если вы используете JavaFX Thread для выполнения такой долговременной работы, вы прекращаете обновление пользовательского интерфейса и т. д. Таким образом, вы должны запускать своего работника в разреженном потоке. Если вы запускаете отдельный поток, все действия GUI, такие как progress.setProgress(), должны быть переданы обратно в поток JavaFX с использованием runLater(), поскольку JavaFX не является многопоточным.

Попробуйте это в действии:

submit.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent event) { 
      double size = 10.0; 
      new Thread(){ 
       public void run() { 
        for (double i = 0.0; i < size; i++){ 
         final double step = i; 
         Platform.runLater(() -> progress.setProgress(step/size)); 
         System.out.printf("Complete: %02.2f%n", i * 10); 

         try { 
          Thread.sleep(1000); 
         } catch(InterruptedException ex) { 
          Thread.currentThread().interrupt(); 
         } 
        } 
       } 
      }.start(); 
     } 

    }); 
1

Вы блокируете поток JavaFX событий вам нужно, чтобы сделать работу в другом потоке и синхронизировать обратно только setProgress вызов с Platform.runLater

Смежные вопросы