2009-06-11 17 views
5

¿Cuál es el enfoque general con Java swing para actualizar un área de texto con líneas de texto (por ejemplo, de un subproceso) y luego tener el texto caret fluir a la parte inferior del área de texto a medida que se agrega el texto. También actualice la barra de desplazamiento para que esté en la parte inferior.Java Swing: enfoque para agregar texto de forma dinámica en el área de texto, tener actualización de barra de desplazamiento

Estaba pensando en tener un stringbuffer y anexar texto a eso y luego establecer la cadena en el área de texto y colocar la barra de desplazamiento en la parte inferior.

Respuesta

13

Use append() para agregar el texto, luego setCaretPosition() para asegurarse de desplazarse con él.

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

+1 para recordar para mover el cursor – kdgregory

+0

¿Copiando todo el área de texto en una cadena solo para obtener la longitud? Esto no va a ser seguro para subprocesos. –

+0

Sí, se aplican los procedimientos estándar de roscado Swing. (No me di cuenta de que getText() implicaba copiar cosas; lo cambiaré a getDocument().) –

7

El método append() no hace lo que quiere?

Y aunque no lo haya preguntado: cuando esté generando algo en un hilo de fondo, asegúrese de usar SwingUtilities.invokeLater() para actualizar sus componentes.

1

Si está actualizando desde un hilo, no se olvide de utilizar SwingWorker o algún otro enfoque Hilo de seguridad AWT.

3

De otro hilo, debe usar java.awt.EventQueue.invokeLater para obtener el EDT y luego todo funciona.

Así:

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

Si alguien lee los documentos de la API de JTextArea.append que afirma ser flujos seguros. JDK7 elimina esa afirmación poco probable (recordatorio: el enhebrado es difícil). Como regla general, en Swing tiendo a ir siempre derecho para el modelo/Document.

Creo que si el símbolo de intercalación se encuentra al final, se debe mover después de un apéndice. La única excepción es si no hay texto, debido a la extraña API. Si se ha movido, es probable que no deseemos actualizarlo después de la adición.

Nota: Si hay varios hilos haciendo esto, no necesariamente sabrá cuál llegará primero.

1

Puede actualizar la barra de desplazamiento sin necesidad de leer con doc.length:

scrollbar.setValue(scrollbar.getMaximum()); 

Update (envuelto en Invocar después, código de 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

y envuelto en invokeLater, por favor actualice su respuesta – mKorbel

+0

No estoy realmente interesado en este hilo de seguridad, pero espero que esto es lo que quería. – fachexot

Cuestiones relacionadas