2016-07-14 13 views
-1

Ich fand heraus, dass meine GUI nach 3-4 Sekunden einfriert, wenn ich auf die Schaltfläche "Start" wie "keine Antwort" klicken. Wenn ich weiter auf die App klicke, muss sie herunterfahren.
Jetzt möchte ich das verhindern, aber ich habe keine Ahnung wie. So weit ich weiß, dass JavaFX in einem einzelnen Thread läuft, muss ich daher, um meine TextArea zu aktualisieren, während die Methoden ausgeführt werden, diese Methoden in einem anderen Thread ausführen.
Ich hoffe, dass mir jemand helfen kann.Update TextArea während der Ausführung von Prozessen

Wie sieht mein Projekt aus?

Ich habe einen FXML, einen Controller, einen Handler, einen Transformer, auch einen Writer und eine Reader-Klasse (die in der Handler-Klasse verwendet werden).
Wenn ich auf die Schaltfläche klicke, die an eine Methode im Controller gebunden ist, wird eine Instanz von Handler erstellt und diese ruft den Reader auf, um eine Textdatei einzulesen, die in eine Liste von Strings umgewandelt wird (zeilenweise).
Zusätzlich werden die Zeilen manipuliert. Danach wird der Writer verwendet, um eine neue Datei zu erstellen und die neuen manipulierten Zeilen in diese Datei zu schreiben.
Es ist dem Benutzer auch erlaubt, auf mehr als nur eine Datei zu verweisen.
Was ich will ist, dass der Textbereich immer dann angezeigt wird, wenn der Leser beginnt, eine Datei wie "Die Datei ... wird gelesen" zu lesen.
Dann anhängen "Die Datei ... wird manipuliert", wenn Transformer zum Handeln kommt und dann
"Die Datei ... wird geschrieben", wenn die neuen Zeilen in die neue Datei geschrieben werden. Hier

ist ein Code ..
Controller:

public class FXMLDocumentController implements Initializable { 

@FXML 
private TextArea console; 

@FXML 
private void handleButtonAction(ActionEvent event) { 
    System.out.println("You clicked me!"); 
    Handler hand = new Handler(); 
    hand.handle(files); 
} 

@Override 
public void initialize(URL url, ResourceBundle rb) { 
    // TODO 
}  

} 

Handler:

public class Handler { 

public void handle(List<String> files) { 
    for (String s : files) { 
     List<String> ls = Reader.readFile(s); 
     Writer.writeFile(Transformer.transform(ls)); 
    } 
} 

Wie sollte ich meinen Code ändern, um die TextArea- zu aktualisieren, wenn eine Datei gelesen, manipuliert oder geschrieben?

Info: Ich weiß, dass die Klasse Handler wird nicht kompiliert, wie ich die Initialisierung der Liste „Dateien“ gelöscht, die Strings von Dateipfaden enthält.

Wenn ich relevante Informationen weggelassen habe, zögern Sie nicht zu fragen.
Ich danke Ihnen im Voraus!

+0

Sie sollten sich Aufgaben und Dienste im Parallelitätspaket ansehen: http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm. Und [Platform.runLater()] (https://docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html#runLater-java.lang.Runnable-). – ManoDestra

Antwort

3

Sie sollten die handle() Methode in einem Hintergrund-Thread ausführen:

@FXML 
private void handleButtonAction(ActionEvent event) { 
    System.out.println("You clicked me!"); 

    Thread thread = new Thread(() -> { 
     Handler hand = new Handler(); 
     hand.handle(files); 
    }); 

    // this line means the background thread will not prevent application exit: 
    thread.setDaemon(true); 

    thread.start(); 
} 

Wenn Sie den Textbereich mit dem aktuellen Status aktualisieren möchten, müssen Sie das Platform.runLater() mit auf dem FX Anwendung Faden planen zurück.Wahrscheinlich der sauberste Weg, dies zu tun, ist nicht Platform.runLater() in der Handler Klasse zu haben, aber ein Feld in Handler für „raubend“ Statusmeldungen definieren:

public class Handler { 

    private final Consumer<String> statusMessageProcessor ; 

    public Handler(Consumer<String> statusMessageProcessor) { 
     this.statusMessageProcessor = statusMessageProcessor ; 
    } 

    // default processor does nothing: 
    public Handler() { 
     this(s -> {}); 
    } 

    public void handle(List<String> files) { 
     for (String s : files) { 

      // similarly for other status updates: 
      statusMessageProcessor.accept("The file "+s+" is being read"); 

      List<String> ls = Reader.readFile(s); 
      Writer.writeFile(Transformer.transform(ls)); 
     } 
    } 
} 

und dann

Handler hand = new Handler() ; 

kann dich

Handler hand = new Handler(message -> 
    Platform.runLater(() -> console.appendText(message + "\n"))); 

in der Schaltfläche Handler-Methode.

+0

Ich würde den zweiten Weg bevorzugen, nicht? Wie ich den Zustand sehe, wenn eine Datei gelesen, manipuliert und geschrieben wird, die ich in der ersten Variante nicht sehen kann. s in Handler hand = neuer Handler (s -> Platform.runLater (() -> console.appendText (s + "\ n"))); ist meine initialisierte Liste? – BlackACE

+0

Was meinst du? Hier gibt es nur eine Lösung. Ich habe es nur in zwei Teile aufgeteilt, um besser verständlich zu sein: erstens, wie man den Handler im Hintergrundthread ausführt und zweitens, wie man Updates bereitstellt. –

+0

's' im Aufruf des' Handler'-Konstruktors ist nur der Name des Parameters für das Lambda (also wird die Statusnachricht an 'statusMessageProcessor.accept (...)' übergeben). Sie können es nennen, was Sie wollen (natürlich, wenn Sie es ändern, ändern Sie auch die Verwendung innerhalb von 'console.appendText (...)'). –