2016-07-29 21 views
0

Ich habe die anderen Artikel auf Stackoverflow zu diesem Thema gelesen. Aber keiner von ihnen passt genau zu meinem Problem.JavaFX: Autoscroll von TextArea mit appendText aber ohne Listener

Ich möchte einen Algorithmus in einer TextArea protokollieren. In jeder Iteration des Algorithmus sollte der Text in diesem TextArea über appendText() erweitert werden.

Mein erstes Problem ist: Wo soll ich den neuen Thread erstellen und wie können beide Threads miteinander kommunizieren (GUI und Algorithmus)?

In meinem aktuellen Design habe ich drei wichtige Klassen: Die Ansicht, die die TextArea hält, der Controller, der den Algorithmus und den Algorithmus aufruft, der eine Reihe von Iterationen benötigt und die TextArea (um appendText() aufzurufen - Methode an mehreren Stellen im Code).

In diesem Design ruft der Controller den Algorithmus auf, der Algorithmus iteriert n-mal mit einer for-Schleife und nachdem er beendet ist, zeigt die GUI die Änderungen an. Aber ich möchte, dass die GUI die Änderungen gleichzeitig anzeigt, wenn der Algorithmus die appendText() - Methode aufruft.

Und mein zweites Problem ist die Autoscroll der TextArea. Nach jedem appendText-Aufruf sollte der TextArea komplett durchgeblättert werden. Aber ich denke, die Lösung dieses Problems ist die gleiche Lösung meines ersten Problems.

Ich wäre sehr dankbar für etwas Hilfe.

Antwort

0

Es ist ziemlich unmöglich, Ihre Frage vollständig ohne (viele) mehr Informationen zu beantworten, aber die allgemeine Herangehensweise wäre, dass der Algorithmus einen Rückruf hat, um eine Nachricht zu verarbeiten, die bei jedem Schritt aufgerufen werden kann der Algorithmus. Übergeben Sie vom Controller aus eine Implementierung des Rückrufs, der den Textbereich mit der Nachricht aktualisiert, auf dem FX-Anwendungs-Thread.

Etwas wie:

public class Algorithm { 

    private Consumer<String> statusCallback ; 

    public Algorithm(Consumer<String> statusCallback) { 
     this.statusCallback = statusCallback ; 
    } 

    public Algorithm() { 
     // by default, callback does nothing: 
     this(s -> {}); 
    } 

    public void performAlgorithm() { 

     while (! finished()) { 
      doNextStep(); 
      String statusMessage = getStatus(); 
      statusCallback.accept(statusMessage); 
     } 
    } 
} 

und dann

public class Controller { 

    private View view = ... ; 

    public void startAlgorithm() { 
     Algorithm algorithm = new Algorithm(s -> Platform.runLater(view.appendStatus(s))); 
     Thread t = new Thread(algorithm::performAlgorithm); 
     t.setDaemon(true); 
     t.start(); 
    } 
} 

Für die View Sie tun dann die folgende (beachten Sie, dass Sie mit textArea.setScrollTop(Double.MAX_VALUE); nach unten scrollen kann):

public class View { 
    private TextArea textArea ; 

    public View() { 
     textArea = new TextArea(); 
     // ... 
    } 

    public void appendStatus(String status) { 
     if (!textArea.getText().isEmpty()) { 
      textArea.appendText("\n"); 
     } 
     textArea.appendText(status); 
     textArea.setScrollTop(Double.MAX_VALUE); 
    } 
} 

Diese sollte funktionieren, solange Ihr Algorithmus nicht zu viele Status erzeugt pdates zu schnell (damit sie den FX-Anwendungs-Thread überfluten und verhindern, dass er seine normale Arbeit ausführt).