2012-08-28 44 views
7

Estoy tratando de hacer una GUI para un servicio, que tiene un JTextArea para ver los mensajes, cada mensaje se escribe en una sola línea y se envuelven las palabras si es necesario.Cómo limitar el número de líneas en JTextArea?

Los mensajes llegan a través de un socket, por lo que es simplemente un .append (mensaje) que estoy usando para actualizar el JTextArea, tengo que limitar estas líneas a 50 o 100 y no tengo necesidad de limitar el conteo de caracteres cada línea.

Si hay un método para limitar las líneas numéricas en el JTextArea o si hay un método alternativo para hacerlo?

Realmente podría usar la ayuda en este asunto.

Editar

El problema es que cada cliente puede enviar líneas infinitas, todas estas líneas tienen que ser legible, así que esto no es una simple comprobación del número de líneas en el JTextArea. Necesito eliminar líneas antiguas para ver líneas más nuevas.

+0

si sabe cuántos caracteres están permitidos en una línea de jtextarea solo divida eso por el número total de caracteres en el jtextarea –

+0

Relacionados: http://stackoverflow.com/questions/479182/how-to-limit- jtextarea-max-rows-and-coloums – CloudyMarble

+0

son solo las líneas o filas que necesito limitar en este caso, por lo que el número de caracteres es irrelevante. –

Respuesta

6

¿Sería esto más eficiente?

final int SCROLL_BUFFER_SIZE = 100; 
public void trunkTextArea(JTextArea txtWin) 
{ 
    int numLinesToTrunk = txtWin.getLineCount() - SCROLL_BUFFER_SIZE; 
    if(numLinesToTrunk > 0) 
    { 
     try 
     { 
      int posOfLastLineToTrunk = txtWin.getLineEndOffset(numLinesToTrunk - 1); 
      txtWin.replaceRange("",0,posOfLastLineToTrunk); 
     } 
     catch (BadLocationException ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 
6

Uso this llegar fila y columna

Añadir un DocumentFilter que comprueba cantidad de filas (pase la doc.getLength() offset) y evitar añadir más texto.

O puede crear un JTextArea invisible simulado y agregar todo el texto allí. Luego mida la última línea permitida y corte el texto.

+0

+1 para 'DocumentFilter', y es más rápido. :-) – trashgod

+0

curioso: ¿por qué utilizar el método de utilidad en lugar de textArea.getLine/Start/OfOffset? – kleopatra

+0

hach ​​... creo que lo encontré: las líneas manejadas en ese método son líneas-entre-cr, ¿no las líneas reales tal como aparecen en la vista envuelta? Si eso es verdad ... qué-una-mierda ... – kleopatra

6

A continuación se muestra un DocumentFilter crudo que parece funcionar. Su enfoque básico es permitir que la inserción/apéndice suceda, consultar el número de líneas después del hecho, si es más el máximo, eliminar las líneas desde el inicio según corresponda.

Cuidado: las líneas contadas con los métodos textArea son (muy probablemente, esperando la confirmación de @Stani) lines-between-cr, no las líneas reales tal como se establecen. En función de sus necesidades exactas, que pueden o no propio (si no, utilizar métodos de utilidad del Stan)

Me sorprendió y no del todo seguro de si es seguro

  • sorprendió: el método de inserción ISN' t llamado, necesario para implementar el método de reemplazo en su lugar (en el código de producción listo, probablemente ambos)
  • no estoy seguro si se garantiza que textArea devolverá valores actualizados en los métodos de filtro (probablemente no, entonces la verificación de la longitud puede ser envuelto en un invokeLater)

Algunos código:

public class MyDocumentFilter extends DocumentFilter { 

    private JTextArea area; 
    private int max; 

    public MyDocumentFilter(JTextArea area, int max) { 
     this.area = area; 
     this.max = max; 
    } 

    @Override 
    public void replace(FilterBypass fb, int offset, int length, 
      String text, AttributeSet attrs) throws BadLocationException { 
     super.replace(fb, offset, length, text, attrs); 
     int lines = area.getLineCount(); 
     if (lines > max) { 
      int linesToRemove = lines - max -1; 
      int lengthToRemove = area.getLineStartOffset(linesToRemove); 
      remove(fb, 0, lengthToRemove); 
     } 
    } 
} 

// usage 
JTextArea area = new JTextArea(10, 10); 
((AbstractDocument) area.getDocument()).setDocumentFilter(new MyDocumentFilter(area, 3)); 
1

Mi enfoque funciona con el contenido de JTextPane como documento. Supone que su programa ha agregado texto al final del documento una y otra vez, de modo que cuando llame a doc.getCharacterElement (1), obtendrá básicamente un elemento de hoja que representa la primera línea de código. Esto es lo que queremos eliminar, entonces obtenemos las compensaciones de inicio y fin de ese elemento, y llamamos al método remove para cortar el texto más antiguo.

Esto se pudo realizar de forma selectiva mediante la comprobación de si el número de caracteres en total es superior a un millón (como lo he hecho más adelante), o con base en el número de líneas que ya se ha agregado.

Si desea basarlo en el número de líneas ya agregadas, necesitará un campo que se incrementará cada vez que imprima en JTextPane, de modo que este código se ejecute una vez cada vez que imprima una nueva línea de texto y el conteo excede tu valor máximo.

 JTextPane pane = ... 
     StyledDocument doc = pane.getStyledDocument(); 
     int size = doc.getLength(); 
     if (size > 1000000) { 
      out.println("Size: " + size); 
      out.println(":" + 1); 
      int i = 0; 
      Element e = doc.getCharacterElement(i + 1); 
      int start = e.getStartOffset(); 
      int end = e.getEndOffset(); 

      try { 
       doc.remove(start, end); 
      } catch (BadLocationException e1) { 
       // TODO Auto-generated catch block 
       e1.printStackTrace(); 
      } 
     } 

¡Salud!

Cuestiones relacionadas