2016-06-16 6 views
2

Ich möchte eine JavaFX ProgressBar in einer FXML-Datei von einer anderen Klasse, in einem Controller-Thread initialisiert, definiert aktualisieren. Momentan wird es einfach nicht aktualisiert.JavaFX: Update ProgressBar (@FXML) von Thread

test.fxml

<ProgressBar fx:id="progressBar" prefWidth="5000.0" progress="0.0"> 
    <VBox.margin> 
     <Insets top="3.0" /> 
    </VBox.margin> 
</ProgressBar> 

Controller.java

@FXML 
public static ProgressBar progressBar = new ProgressBar(0); 

MyMain main; 

@FXML 
private void handleStartWork() throws Exception { 
    new Thread() { 
     @Override 
     public void run() { 
      try { 
       main = new MyMain(); 
       main.doIt(); 
      } catch (final Exception v) { 
       // ... 
      } 
     } 
    }.start(); 
} 

MyMain.java

public void doIt(){ 
    while(...){ 
     Platform.runLater(() -> PoCOverviewController.progressBar.setProgress((count/sum) * 100)); 
    } 
} 

ich verschie schon versucht mieten Versionen unter Berücksichtigung der Beiträge mag:

Ich weiß nicht, ob es der richtige Ansatz ist die ProgressBar statisch zu machen. Ich wollte das Objekt einfach nicht durch den Workflow führen.

Update (Xavier Lambros Antwort): Jetzt habe ich versucht, es mit Singletons aber es funktioniert immer noch nicht:

Controller.java

@FXML 
public ProgressBar progressBar = new ProgressBar(0);  

private static Controller INSTANCE = new Controller(); 

public static Controller getInstance() { 
    return INSTANCE; 
} 

public ProgressBar getProgressBar() { 
    return progressBar; 
} 

MyMain.java

public void doIt(){ 
    while(...){ 
     Platform.runLater(() -> Controller.getInstance().getProgressBar() 
       .setProgress((count/sum) * 100)); 
    } 
} 
+0

Mögliches Duplikat von [Kompatibilitätsprobleme mit javafx 8 - statische FXML-Felder] (http://stackoverflow.com/questions/23105433/javafx-8-compatibility-issues-fxml-static-fields) – fabian

+0

@fabian Der statische Modifikator wurde entfernt von ProgressBar, funktioniert aber auch nicht. –

+0

Sind 'count' und' sum' 'int's oder' long''? Dann sollte die folgende Frage helfen: http://stackoverflow.com/questions/4685450/why-is-the-result-of-1-3-0 – fabian

Antwort

0

Ich glaube nicht, dass ProgressBar statisch sein kann.

Mein Weg ist ein Accessor auf der ProgressBar in Ihrem Controller und init den Controller wie diese haben:

FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/YourController.fxml"); 
loader.load(); 

Nachdem Sie Ihre ProgressBar mit zugreifen:

loader.<YourController>getController().getProgressBar(); 

Wenn Sie brauchen , um es in verschiedenen Klassen, viele andere Möglichkeiten zu erreichen, ist es eine Singleton zu machen:

es zu nennen:

Singleton.getInstance().getProgressBar(); 
+0

So gibt es eine Möglichkeit, "loader. getController(). GetProgressBar();" in meiner MyMain.java-Klasse, da es kein FXMLLoader-Objekt gibt? –

+0

Setzen Sie Ihre MyMain.java –

+0

Als Neuling auf Stackoverflow, kann ich nicht direkt Ihre Frage kommentieren. Aber ich denke, Sie können Ihren Controller nicht direkt zu einem Singleton machen. Singleton sollte eine andere Klasse sein. FXML Controller sind spezifisch und müssen einige Regeln beachten. Ansonsten verstehe ich nicht, warum du keinen FXMLLoader in deinem MyMain hast, weil im javaFX-Projekt MyMain Szenen-Init enthalten sollte ... Wie auch immer, die Idee von Singleton besteht darin, deine Fortschrittsleiste in der Init deines Controllers zu speichern und zu machen Es zugänglich überall in Ihrem Projekt auf sie zugreifen werfen das Singleton, das ein Design-Muster ist. –

3

Wie in javafx 8 compatibility issues - FXML static fields erwähnt, können Sie keine @FXML -annotated Feld machen static (und es macht keinen Sinn, dies zu tun: Diese Felder sind von Natur aus Eigenschaften des spezifischen Controller Instanz).

die doIt() Methode Zugriff auf den Fortschrittsbalken ermöglichen, man konnte es nur als Parameter direkt übergeben:

@FXML 
public ProgressBar progressBar ; 

MyMain main; 

@FXML 
private void handleStartWork() throws Exception { 
    new Thread() { 
     @Override 
     public void run() { 
      try { 
       main = new MyMain(); 
       main.doIt(progressBar); 
      } catch (final Exception v) { 
       // ... 
      } 
     } 
    }.start(); 
} 

und dann

public void doIt(ProgressBar progressBar){ 
    while(...){ 
     Platform.runLater(() -> progressBar.setProgress((count/sum) * 100)); 
    } 
} 

Unter bestimmten Umständen könnte es nicht sinnvoll für die Klasse Main eine Abhängigkeit von der JavaFX-API zu haben. In diesem Fall könnten Sie nur eine Funktion übergeben, die den Fortschrittsbalken aktualisiert:

@FXML 
public ProgressBar progressBar ; 

MyMain main; 

@FXML 
private void handleStartWork() throws Exception { 
    new Thread() { 
     @Override 
     public void run() { 
      try { 
       main = new MyMain(); 
       main.doIt(progressBar::setProgress); 
      } catch (final Exception v) { 
       // ... 
      } 
     } 
    }.start(); 
} 

und

public void doIt(DoubleConsumer progressUpdate){ 
    while(...){ 
     Platform.runLater(() -> progressUpdate.accept((count/sum) * 100)); 
    } 
} 

Beachten Sie, dass Sie haben nicht gezeigt, was in Ihrer while Schleife passiert: wenn Sie einreichen zu viele Runnables zum FX-Anwendungs-Thread, könnten Sie es "überfluten" und verhindern, dass es in einer angemessenen Zeit aktualisiert wird. Sie könnten eine Task verwenden, die über eine spezielle API zum Aktualisieren eines Fortschrittsfelds verfügt, an die die Eigenschaft progress des Fortschrittsbalkens gebunden werden kann. Wenn es immer noch nicht funktioniert, sollten Sie Ihre Frage so bearbeiten, dass sie eine MCVE enthält.