2012-08-28 15 views
7

Sto provando a creare una GUI per un servizio, che dispone di un JTextArea per visualizzare i messaggi, ogni messaggio è scritto su una singola riga e wordwrapped se necessario.Come limitare il numero di righe in JTextArea?

I messaggi arrivano tramite un socket, quindi è semplicemente un .append (messaggio) che sto usando per aggiornare il JTextArea, ho bisogno di limitare queste righe a 50 o 100 e non ho bisogno di limitare il conteggio dei caratteri su ogni linea.

Se esiste un metodo per limitare le righe numeriche in JTextArea o se esiste un metodo alternativo per farlo?

Potrei davvero usare l'assistenza in questa materia.

Modifica

Il problema è che ogni cliente può inviare linee infinite, tutte queste linee devono essere leggibili, quindi questo non è un semplice controllo del numero di righe nel JTextArea. Ho bisogno di rimuovere le vecchie linee per visualizzare le nuove linee.

+0

se si sa quanti caratteri sono consentiti in una riga di jtextarea, basta dividerlo per il numero di caratteri totali nella jtextarea –

+0

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

+0

in questo caso sono solo le righe o le righe che devo limitare, quindi il numero di caratteri è irrilevante. –

risposta

6

Sarebbe più efficiente?

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

Usa this per ottenere riga e colonna

Aggiungi un DocumentFilter che controlla quantità di righe (passare il doc.getLength() offset) e prevenire l'aggiunta più testo.

Oppure puoi creare un fittizio JTextArea invisibile e aggiungere tutto il testo lì. Quindi misurare l'ultima linea consentita e tagliare il testo.

+0

+1 per 'DocumentFilter' ed essendo più veloce. :-) – trashgod

+0

curioso: perché usare il metodo di utilità invece di textArea.getLine/Start/OfOffset? – kleopatra

+0

hach ​​... penso di averlo trovato: le linee gestite con quei metodi sono le linee-tra-cr, non le linee effettive come appaiono nella vista avvolta? Se è vero ... che schifo ... – kleopatra

6

Di seguito è riportato un grezzo DocumentFilter che sembra funzionare. Il suo approccio di base è lasciare che l'inserimento/l'append avvenga, interrogare il numero di righe dopo il fatto, se più il massimo, rimuovere le righe dall'inizio come appropriato.

Attenzione: le linee contate con i metodi textArea sono (molto probabilmente, in attesa di conferma da @Stani) linee-tra-cr, non le linee effettive come layout. A seconda del vostro requisito esatto, essi possono o non possono Suite è (se non, utilizzare metodi di utilità del Stan)

Sono rimasto sorpreso e non del tutto sicuro se è sicuro

  • sorpreso: il metodo di inserimento isn' t chiamato, necessario per implementare il metodo replace invece (nel codice di produzione probabilmente entrambi)
  • non sicuro se textArea è garantito per restituire valori aggiornati nei metodi di filtro (probabilmente no, quindi il controllo della lunghezza può essere avvolto in un invokeLater)

Qualche codice:

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

Il mio approccio funziona con il contenuto di JTextPane come documento. Si presume che il tuo programma abbia aggiunto il testo alla fine del documento più e più volte, in modo che quando chiami doc.getCharacterElement (1), otterrai sostanzialmente un elemento foglia che rappresenta la prima linea di codice. Questo è ciò che vogliamo eliminare, quindi otteniamo gli offset di inizio e fine di quell'elemento e chiamiamo il metodo remove per tagliare il testo meno recente.

Questo potrebbe essere eseguito in modo selettivo controllando se il numero di caratteri totale è maggiore di un milione (come ho fatto di seguito), o in base al numero di linee che hai già aggiunto.

Se si desidera basarlo sul numero di righe già aggiunte, sarà necessario un campo che viene incrementato ogni volta che si stampa su JTextPane, in modo che questo codice venga eseguito una volta ogni volta che si stampa una nuova riga di testo e il conteggio supera il valore massimo.

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

Cheers!