2009-06-11 8 views
5

Qual è l'approccio generale con Java swing per aggiornare un'area di testo con linee di testo (ad esempio da una discussione) e quindi far passare il flusso di testo al fondo dell'area di testo mentre viene aggiunto del testo. Aggiorna anche la barra di scorrimento in modo che si trovi in ​​basso.Java Swing: approccio per aggiungere dinamicamente il testo nell'area di testo, aggiornare la barra di scorrimento

Stavo pensando che avrei un stringbuffer e aggiungere testo a quello e quindi impostare la stringa nella textarea e posizionare la barra di scorrimento in basso.

risposta

13

Utilizzare append() per aggiungere il testo, quindi setCaretPosition() per accertarsi di farlo scorrere.

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

+1 per ricordare per spostare il cursore – kdgregory

+0

Copia l'intera area di testo in una stringa solo per ottenere la lunghezza? Questo non sarà sicuro per i thread. –

+0

Sì, si applicano le procedure di filettatura Swing standard. (Non mi sono reso conto che getText() implicava la copia di cose, lo cambierò in getDocument()). –

7

Il metodo append() non fa quello che vuoi?

E anche se non hai chiesto: quando stai generando qualcosa in un thread in background, assicurati di usare SwingUtilities.invokeLater() per aggiornare i tuoi componenti.

1

Se si sta aggiornando da un thread, non dimenticate di utilizzare SwingWorker o qualche altro metodo thread-safe AWT.

3

Da un altro thread, è necessario utilizzare java.awt.EventQueue.invokeLater per accedere all'EDT e quindi tutto funziona.

Quindi:

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()); 
    } 
}}); 

Se qualcuno di leggere la documentazione API per JTextArea.append che dice di essere thread-safe. JDK7 rimuove questa affermazione improbabile (promemoria: il threading è difficile). Di norma, in Swing tendo ad andare sempre dritto per il modello/Document.

Credo che se il cursore è alla fine dovrebbe essere spostato dopo un'appendice. L'unica eccezione è se non c'è testo, a causa della strana API. Se è stato spostato, probabilmente non vogliamo aggiornarlo dopo l'aggiunta.

Nota: se più thread stanno facendo questo, non si sa necessariamente quale sarà il primo.

1

È possibile aggiornare la barra di scorrimento senza leggere doc.length con:

scrollbar.setValue(scrollbar.getMaximum()); 

Update (avvolto in Invoke dopo, il codice da 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

e avvolto in invokeLater, si prega di aggiornare la risposta – mKorbel

+0

Non sono molto interessato a questo problema di sicurezza dei thread, ma spero che questo sia ciò che volevate. – fachexot

Problemi correlati