2013-07-22 27 views
12

Sto tentando di ottenere un'Area di testo per lo scorrimento automatico verso il basso con un nuovo testo che viene inserito tramite un gestore di eventi. Ogni nuova voce è solo una lunga stringa di testo con ogni voce separata da un'interruzione di riga. Ho provato un gestore di modifiche che imposta setscrolltop su Double.MIN_VALUE ma senza successo. Qualche idea su come questo potrebbe essere fatto?JavaFX TextArea e autoscroll

+1

Il tuo commento è stato cancellato (non da me) perché lo hai postato come risposta. Ti ho risposto che potresti voler accettare la risposta che giudichi corretta per far sapere agli altri che hai trovato una soluzione che ti soddisfa. Per fare ciò, fai clic su "V" oltre alla risposta che preferisci rendendola verde. Ciò è valido anche per le [proprie risposte] (http://stackoverflow.com/questions/19122056/camel-jpa-component-forcing-a-commit) – Math

risposta

20

si deve aggiungere un listener all'elemento TextArea per scorrere fino alla fine, quando il suo valore è cambiato:

@FXML private TextArea txa; 

... 

txa.textProperty().addListener(new ChangeListener<Object>() { 
    @Override 
    public void changed(ObservableValue<?> observable, Object oldValue, 
      Object newValue) { 
     txa.setScrollTop(Double.MAX_VALUE); //this will scroll to the bottom 
     //use Double.MIN_VALUE to scroll to the top 
    } 
}); 

Ma questo ascoltatore non viene attivato quando si utilizza il metodo setText(text), quindi se si vuole innescare dopo un setText(text) utilizzare il appendText(text) subito dopo:

txa.setText("Text into the textArea"); //does not trigger the listener 
txa.appendText(""); //this will trigger the listener and will scroll the 
        //TextArea to the bottom 

Questo suona più come un insetto, una volta che il setText() dovrebbe innescare il changed ascoltatore, tuttavia d oesn't. Questa è la soluzione che uso io e spero che ti aiuti.

+2

'setScrollTop (Double.MIN_VALUE);' scorre verso l'alto, mentre 'MAX_VALUE' scorre verso il basso. –

+0

@AdamJensen Farò un test qui, perché ho risposto a questo qualche tempo fa e non riesco a ricordare semplicemente guardandolo. Grazie per la segnalazione. – Math

+1

@AdamJensen avevi assolutamente ragione. L'ho appena risolto. Grazie! – Math

7

txa.appendText ("") scorre verso il basso senza un ascoltatore. Questo diventa un problema se si desidera tornare indietro e il testo viene costantemente aggiornato. txa.setText ("") riporta la barra di scorrimento in alto e si applica lo stesso problema.

La mia soluzione era estendere la classe TextArea, ammendando il tag FXML da textArea a LogTextArea. Dove questo funziona, provoca chiaramente problemi nel generatore di scena in quanto non sa che questo componente è

import javafx.scene.control.TextArea; 
import javafx.scene.text.Font; 

public class LogTextArea extends TextArea { 

private boolean pausedScroll = false; 
private double scrollPosition = 0; 

public LogTextArea() { 
    super(); 
} 

public void setMessage(String data) { 
    if (pausedScroll) { 
     scrollPosition = this.getScrollTop(); 
     this.setText(data); 
     this.setScrollTop(scrollPosition); 
    } else { 
     this.setText(data); 
     this.setScrollTop(Double.MAX_VALUE); 
    } 
} 

public void pauseScroll(Boolean pause) { 
    pausedScroll = pause; 
} 

} 
3

alternativo a quello strano bug setText senza utilizzare appendText

textArea.selectPositionCaret(textArea.getLength()); 
textArea.deselect(); //removes the highlighting 
1

un addendum vorrei aggiungere a jamesarbrown di la risposta sarebbe a questo sarebbe di utilizzare una proprietà booleana invece in modo da poter accedere da dentro FXML. Qualcosa di simile.

import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.scene.control.TextArea; 

public class LogTextArea extends TextArea { 
    private final BooleanProperty pausedScrollProperty = new SimpleBooleanProperty(false); 
    private double scrollPosition = 0; 

    public LogTextArea() { 
     super(); 
    } 

    public void setMessage(String data) { 
     if (isPausedScroll()) { 
      scrollPosition = this.getScrollTop(); 
      this.setText(data); 
      this.setScrollTop(scrollPosition); 
     } else { 
      this.setText(data); 
      this.setScrollTop(Double.MAX_VALUE); 
     } 
    } 

    public final BooleanProperty pausedScrollProperty() { return pausedScrollProperty; } 
    public final boolean isPausedScroll() { return pausedScrollProperty.getValue(); } 
    public final void setPausedScroll(boolean value) { pausedScrollProperty.setValue(value); } 
} 

Tuttavia, il problema di questa risposta è che se vieni inondato con una irragionevolmente grandi quantità di input (come può accadere durante il recupero di un registro da un IO Stream) il filo JavaFX si blocca perché il TextArea ottiene troppi dati