2013-03-19 4 views
5

Cerco di capire come aggiornare un ProgressBar in un ambiente con multithreading. Sto facendo qualcosa di sbagliato qui, ma non vedo cosa sia. Questo dovrebbe semplicemente riempire la barra ogni 3 secondi ma non lo fa:JavaFx ProgressBar non aggiorna

  Task<Void> task = new Task<Void>(){ 
       @Override 
       public Void call(){ 
        for (int i = 1; i < 10; i++) { 
         try { 
          Thread.sleep(3000); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
         System.out.println(i); 
         updateProgress(i , 10); 
        } 
       return null;     
       } 
      }; 

      updProg = new ProgressBar(); 
      updProg.progressProperty().bind(task.progressProperty()); 

      Thread th = new Thread(task); 
      th.setDaemon(true); 
      th.start(); 

Cosa mi manca?

risposta

8

Il tuo campione funziona bene per me.

Il campione riempie leggermente la barra ogni 3 secondi, riempiendo completamente la barra in mezzo minuto.

L'ho appena inserito in un codice di scaffolding per renderlo eseguibile e ha funzionato senza modifiche (java7u15, win7).

simpletaskprogress

import javafx.application.Application; 
import javafx.concurrent.Task; 
import javafx.scene.*; 
import javafx.scene.control.*; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class ProgressTest extends Application { 
    public static void main(String[] args) { Application.launch(args); } 
    @Override public void start(Stage stage) { 
    Task<Void> task = new Task<Void>() { 
     @Override public Void call() { 
     for (int i = 0; i < 10; i++) { 
      try { 
      Thread.sleep(100); 
      } catch (InterruptedException e) { 
      Thread.interrupted(); 
      break; 
      } 
      System.out.println(i + 1); 
      updateProgress(i + 1, 10); 
     } 
     return null; 
     } 
    }; 

    ProgressBar updProg = new ProgressBar(); 
    updProg.progressProperty().bind(task.progressProperty()); 

    Thread th = new Thread(task); 
    th.setDaemon(true); 
    th.start(); 

    StackPane layout = new StackPane(); 
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;"); 
    layout.getChildren().add(updProg); 

    stage.setScene(new Scene(layout)); 
    stage.show(); 
    } 
} 

Forse avete usato una qualche versione di accesso precoce di Java 8, che aveva un bug in esso (ora risolto) intorno aggiornamenti ProgressBar.

RT-29018 ProgressBar and ProgressIndicator disappear when progressProperty is updated

+0

Ho copiato il codice e funziona solo perfettamente. Ho integrato male in qualche modo? Lo sto usando in una sottoclasse e devo accedere alla barra di avanzamento in modo statico. questo potrebbe causare qualche problema? Sto usando 7v17 btw – Chromos

+0

edit: il gui è progettato in un foglio fxml. – Chromos

+0

Quindi la patch è già disponibile @jewelsea? –

1

Si sta utilizzando l'ultima JDK 8 Early-Access? In tal caso, vedere questo bug report che ho archiviato: http://javafx-jira.kenai.com/browse/RT-29018

Fondamentalmente, in una recente versione della build di accesso anticipato, hanno apportato alcune modifiche alle skin e ai CSS. Ciò ha causato la rivelazione di un bug nascosto in cui i nodi figlio sono più sporchi dei nodi principali, ma entrambi devono ridisegnare nello stesso impulso, il livello di dirty del genitore finisce sovrascrivendo il livello dirty dei nodi figli.

In questo modo il progresso non viene visualizzato e, di fatto, per me lo progressBar è diventato completamente invisibile, non appena updateProgress è stato chiamato dall'attività. Hanno una patch in atto, non so quando questo passerà.

un work-around, utilizzare jdk7 in attesa sulla patch, o si può fare quello che ho fatto e applicare questo dal vecchio CSS nel vostro CSS foglio di stile:

/*hack to get progress bar working. From: JDK7u17 jfxrt.jar!/com/sun/javafx/scene/control/skin/caspian/caspian.css */ 

/******************************************************************************* 
*                    * 
* ProgressBar                 * 
*                    * 
******************************************************************************/ 

.progress-bar { 
    -fx-skin: "com.sun.javafx.scene.control.skin.ProgressBarSkin"; 
    -fx-background-color: 
     -fx-box-border, 
     linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%)); 
    -fx-background-insets: 0, 1; 
    -fx-indeterminate-bar-length: 60; 
    -fx-indeterminate-bar-escape: true; 
    -fx-indeterminate-bar-flip: true; 
    -fx-indeterminate-bar-animation-time: 2; 
    -fx-focus-traversable: true; 
} 

.progress-bar .bar { 
    -fx-background-color: 
     -fx-box-border, 
     linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)), 
     linear-gradient(to bottom, derive(-fx-accent,38%), -fx-accent); 
    -fx-background-insets: 0, 1, 2; 
    -fx-padding: 0.416667em; /* 5 */ 
} 

.progress-bar:indeterminate .bar { 
    -fx-background-color: linear-gradient(to left, transparent, -fx-accent); 
} 

.progress-bar .track { 
    -fx-background-color: 
     -fx-box-border, 
     linear-gradient(to bottom, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%)); 
    -fx-background-insets: 0, 1; 
} 

.progress-bar:disabled { 
    -fx-opacity: 1.0 
} 
+0

per la tua risposta. Il fatto è che sto usando effettivamente jre 7v17. Testato su win7 e ubuntu e non ha funzionato. Ma l'esatto esempio della risposta di jewelsas ha funzionato bene. Deve avere qualcosa da fare come ho implementato il ProgressBar – Chromos

0

Se è stato definito updProg nel File FXML, quindi il problema potrebbe essere l'inizializzazione qui.

cercare di rimuovere solo questa linea:

updProg = new ProgressBar(); 
+0

Perché il downvote? – Chaiavi

+0

Per favore, se qualcuno downvote, mantenere un commento su di esso, così il poster può correggere la sua risposta, e può ottenere upvote. –

0
Timeline updateProgressBar = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent event) { 
         /*Where Seconds and TotalSeconds are counter and total 
         respectively, also put somewhere Seconds++ or 
         however you want to update progress. This time line 
         will reapit each second */ 
         progressBar.setProgress(Seconds/TotalSeconds); 
       } 
    })); 
    updateProgressBar.setCycleCount(Timeline.INDEFINITE); 
    updateProgressBar.play();