2009-06-11 12 views
5

Jakie jest ogólne podejście do swingowania Java, aby zaktualizować tekst z liniami tekstu (np. Z wątku), a następnie przesuwać tekst na dół z textarea podczas dodawania tekstu. Zaktualizuj pasek przewijania tak, aby znajdował się na dole.Java Swing: Podejście do dynamicznego dołączania tekstu w obszarze tekstowym, aktualizacja paska przewijania

Myślałem, że będę miał bufor stringów i dopiszę do niego tekst, a następnie ustawię ciąg w polu tekstowym i ustawiam pasek przewijania na dole.

Odpowiedz

13

Użyj append(), aby dodać tekst, a następnie setCaretPosition(), aby się upewnić, że go przewiniesz.

myTextPane.append(textFromSomewhere); 
myTextPane.setCaretPosition(myTextPane.getDocument().getLength()); 
+0

+1 dla pamiętając, aby przesunąć kursor – kdgregory

+0

Kopiowanie całego obszaru tekstowego do String tylko po to, by uzyskać jego długość? To nie będzie bezpieczne dla wątków. –

+0

Tak, obowiązują standardowe procedury gwintowania Swing. (Nie zdawałem sobie sprawy, że getText() wymaga kopiowania rzeczy, zmienię to na getDocument().) –

7

Metoda append() nie robi, co chcesz?

Mimo że nie zapytano: podczas generowania czegoś w wątku w tle, należy użyć polecenia SwingUtilities.invokeLater(), aby zaktualizować składniki.

1

Jeśli aktualizujesz z wątku, nie zapomnij użyć SwingWorker lub innego podejścia bezpieczny wątku AWT.

3

Z innego wątku powinieneś użyć java.awt.EventQueue.invokeLater, aby dostać się do EDT, a następnie wszystko działa.

Więc:

java.awt.EventQueue.invokeLater(new Runnable() { public void run() { 
    Document doc = text.getDocument(); 
    int origLen = doc.getLength() 
    try { 
     doc.insertString(origLen, msg, null); 
    } catch (BadLocationException exc) { 
     // Odd APIs forces us to deal with this nonsense. 
     IndexOutOfBoundsException wrapExc = new IndexOutOfBoundsException(); 
     wrapExc.initCause(exc); 
     throw wrapExc; 
    } 
    // IIRC, Position is a bit odd and 
    if (origLen == 0) { 
     text.setCaretPosition(doc.getLength()); 
    } 
}}); 

Gdyby ktoś odczytać docs API dla JTextArea.append twierdzi, że jest bezpieczny wątku. JDK7 usuwa to mało prawdopodobne żądanie (przypomnienie: wątki są trudne). Z reguły w Swingu zawsze zmierzam prosto do modelu/Document.

Wierzę, że jeśli karetka jest na końcu, należy ją przesunąć po dodaniu. Jedynym wyjątkiem jest brak tekstu z powodu dziwnego API. Jeśli został przeniesiony, prawdopodobnie nie chcemy go aktualizować po dodaniu.

Uwaga: jeśli robi to wiele wątków, niekoniecznie wiadomo, które zostaną przesłane jako pierwsze.

1

można zaktualizować pasek przewijania bez czytania doc.length z:

scrollbar.setValue(scrollbar.getMaximum()); 

Update (zawinięte w Invoke później kod z Tom Hawtin)

java.awt.EventQueue.invokeLater(new Runnable() { public void run() { 
    try { 
     textArea.append(msg); 
    } catch (BadLocationException exc) { 
     // Odd APIs forces us to deal with this nonsense. 
     IndexOutOfBoundsException wrapExc = new IndexOutOfBoundsException(); 
     wrapExc.initCause(exc); 
     throw wrapExc; 
    } 
    JScrollBar bar = scrollPane.getVerticalScrollBar(); 
    bar.setValue(bar.getMaximum()); 
}}); 
+0

i zapakowane w invokeLater, proszę zaktualizować odpowiedź – mKorbel

+0

Nie jestem naprawdę w tym wątku bezpieczeństwa rzeczą, ale mam nadzieję, że to, co chciałeś. – fachexot

Powiązane problemy