2015-04-14 10 views
6

Come visualizzare la barra di avanzamento tramite popup e chiudere automaticamente se il processo è terminato. Ecco il mio codice.Mostra popup con ProgressBar in JavaFX

Task<ProgressForm> task = new Task<ProgressForm>() { 
      @Override 
      public ProgressForm call() throws InterruptedException{ 
       ProgressForm pf = new ProgressForm(); 
       for (int i = 1; i <= 10; i++) { 
        pf.activateProgressBar(this); 
        updateProgress(i, 10); 
       } 
      return pf;     
      } 
     }; 

     task.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 
      @Override 
      public void handle(WorkerStateEvent t) { 
       ProgressForm pf = (ProgressForm)task.getValue(); 
       pf.getDialogStage().close(); 
      } 
     }); 

     Thread th = new Thread(task); 
     th.run(); 

Progress classe form:

private final Stage dialogStage; 
private final ProgressBar pb = new ProgressBar(); 
private final ProgressIndicator pin = new ProgressIndicator(); 

public ProgressForm() { 
    dialogStage = new Stage(); 
    dialogStage.initStyle(StageStyle.UTILITY); 
    dialogStage.setResizable(false); 
    dialogStage.initModality(Modality.APPLICATION_MODAL); 

    // PROGRESS BAR 
    final Label label = new Label(); 
    label.setText("alerto"); 

    pb.setProgress(-1F); 
    pin.setProgress(-1F); 

    final HBox hb = new HBox(); 
    hb.setSpacing(5); 
    hb.setAlignment(Pos.CENTER); 
    hb.getChildren().addAll(pb, pin); 

    Scene scene = new Scene(hb); 
    dialogStage.setScene(scene); 
} 

public void activateProgressBar(final Task task) throws InterruptedException { 
    pb.progressProperty().bind(task.progressProperty()); 
    pin.progressProperty().bind(task.progressProperty()); 
    dialogStage.show(); 
} 

public Stage getDialogStage() { 
    return dialogStage; 
} 

Il problema con questo codice è

  1. se io uso .Show(), la visualizzazione di pop-up è liscia ma nessun progresso BAR.
  2. se uso .showAndWait(), la visualizzazione di pop-up richiede l'uscita manuale per il pop-up per chiudere MA Visualizza la barra di avanzamento.

Qualche idea/idea su questo?

risposta

14

Le due regole per multithreading in JavaFX sono:

  1. codice che modifica l'interfaccia utente (crea un Stage o cambia proprietà di nodi che sono parte di un grafico scena) deve essere eseguito sul Thread di applicazioni JavaFX. La violazione di questa regola comporta il lancio di IllegalStateException s o può comportare un comportamento imprevedibile.
  2. Codice che impiega molto tempo per eseguire se deve essere eseguito in un thread in background (ad esempio, non il Thread di applicazione FX). La violazione di questa regola farà sì che l'interfaccia utente non risponda.

Il codice viola la prima regola, perché chiama il costruttore ProgressForm in un thread in background. Devi prima configurare l'interfaccia utente, mostrare la finestra di dialogo e quindi avviare il thread in background.

Si noti che non è necessario associare ripetutamente le proprietà progress della barra di avanzamento e dell'indicatore alla proprietà progress dell'attività. Una volta legato, rimarrà legato fino a quando non lo si disfa.

È piuttosto difficile correggere il codice così com'è, perché l'attività in background non esegue in realtà nulla che richieda tempo. Ecco una versione di quello che stai facendo con una pausa:

import javafx.application.Application; 
import javafx.concurrent.Task; 
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.control.ProgressIndicator; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Modality; 
import javafx.stage.Stage; 
import javafx.stage.StageStyle; 

public class ProgressDialogExample extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Button startButton = new Button("Start"); 
     startButton.setOnAction(e -> { 
      ProgressForm pForm = new ProgressForm(); 

      // In real life this task would do something useful and return 
      // some meaningful result: 
      Task<Void> task = new Task<Void>() { 
       @Override 
       public Void call() throws InterruptedException { 
        for (int i = 0; i < 10; i++) { 
         updateProgress(i, 10); 
         Thread.sleep(200); 
        } 
        updateProgress(10, 10); 
        return null ; 
       } 
      }; 

      // binds progress of progress bars to progress of task: 
      pForm.activateProgressBar(task); 

      // in real life this method would get the result of the task 
      // and update the UI based on its value: 
      task.setOnSucceeded(event -> { 
       pForm.getDialogStage().close(); 
       startButton.setDisable(false); 
      }); 

      startButton.setDisable(true); 
      pForm.getDialogStage().show(); 

      Thread thread = new Thread(task); 
      thread.start(); 
     }); 

     StackPane root = new StackPane(startButton); 
     Scene scene = new Scene(root, 350, 75); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

    } 

    public static class ProgressForm { 
     private final Stage dialogStage; 
     private final ProgressBar pb = new ProgressBar(); 
     private final ProgressIndicator pin = new ProgressIndicator(); 

     public ProgressForm() { 
      dialogStage = new Stage(); 
      dialogStage.initStyle(StageStyle.UTILITY); 
      dialogStage.setResizable(false); 
      dialogStage.initModality(Modality.APPLICATION_MODAL); 

      // PROGRESS BAR 
      final Label label = new Label(); 
      label.setText("alerto"); 

      pb.setProgress(-1F); 
      pin.setProgress(-1F); 

      final HBox hb = new HBox(); 
      hb.setSpacing(5); 
      hb.setAlignment(Pos.CENTER); 
      hb.getChildren().addAll(pb, pin); 

      Scene scene = new Scene(hb); 
      dialogStage.setScene(scene); 
     } 

     public void activateProgressBar(final Task<?> task) { 
      pb.progressProperty().bind(task.progressProperty()); 
      pin.progressProperty().bind(task.progressProperty()); 
      dialogStage.show(); 
     } 

     public Stage getDialogStage() { 
      return dialogStage; 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+1

buona giornata! ho provato il tuo codice ma sembra che il palco non mostri la mia barra di avanzamento. l'aspetto di esso: http://pasteboard.co/2zCr2Qbx.png – user3247087

+0

Hai eseguito il codice esatto che ho postato? Ha funzionato bene per me. Quali JDK e OS stai usando? –

+0

è stato in grado di risolvere un problema del mio problema. in questo momento devo correggere come evitare il blocco dell'interfaccia utente ogni volta che chiamo waitFor per un determinato processo. sembra che la mia barra di avanzamento non venga visualizzata a causa di waitFor(). – user3247087