JTextArea Anzahl Zeichen begrenzen

Hallo,

ich habe eine JTextArea bei der maximal 10000 Zeichen eingegeben werden dürfen.

Ich habe folgenden Code:

private JTextArea content;
private final int MAX_LEN = 10000;

content.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e)
{
if(content.getDocument().getLength() > MAX_LEN){

          	  try {
            	content.getDocument().remove(MAX_LEN, content.getDocument().getLength());           
        		
    	      } catch (BadLocationException ex) {
  
              }
        	}	
        }
        
        public void removeUpdate(DocumentEvent e)
        {
        	if(content.getDocument().getLength() > MAX_LEN){
            	
          	  try {
            	content.getDocument().remove(MAX_LEN, content.getDocument().getLength());           
        		
    	      } catch (BadLocationException ex) {
  
              }
        	}	
        }
        
        public void changedUpdate(DocumentEvent e)
        {
        	if(content.getDocument().getLength() > MAX_LEN){
            	
          	  try {
            	content.getDocument().remove(MAX_LEN, content.getDocument().getLength());           
        		
    	      } catch (BadLocationException ex) {
  
              }
        	}	
        }

Ich erhalte folgende Exception:

Exception in thread „AWT-EventQueue-0“ java.lang.IllegalStateException: Attempt to mutate in notification
at java.desktop/javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1372)
at java.desktop/javax.swing.text.AbstractDocument.remove(AbstractDocument.java:614)
at view.MainView$1.insertUpdate(MainView.java:100)
at java.desktop/javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:227)
at java.desktop/javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:781)
at java.desktop/javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:740)
at java.desktop/javax.swing.text.PlainDocument.insertString(PlainDocument.java:131)
at java.desktop/javax.swing.text.AbstractDocument.replace(AbstractDocument.java:699)
at java.desktop/javax.swing.text.JTextComponent.replaceSelection(JTextComponent.java:1335)

...

Die Exception tritt hier auf:

content.getDocument().remove(MAX_LEN, content.getDocument().getLength());

phind.com (also openAI) meint, ein DocumetFilter wäre besser…

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class LimitDocumentFilter extends DocumentFilter {
    
    private int limit;

    public LimitDocumentFilter(int limit) {
        if (limit <= 0) {
            throw new IllegalArgumentException("Limit can not be <= 0");
        }
        this.limit = limit;
    }

    @Override
    public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
        if (this.isAllowed(fb, string)) {
            super.insertString(fb, offset, string, attr);
        }
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException {
        if (this.isAllowed(fb, string)) {
            super.replace(fb, offset, length, string, attr);
        }
    }

    private boolean isAllowed(FilterBypass fb, String string) {
        return (fb.getDocument().getLength() + string.length()) <= this.limit;
    }
}

JTextArea textArea = new JTextArea();
((AbstractDocument) textArea.getDocument()).setDocumentFilter(new LimitDocumentFilter(10000));

Ich habe es jetzt so gelöst:

            content.getDocument().addDocumentListener(new DocumentListener() {
                public void insertUpdate(DocumentEvent e)
                {
                	  countText();
              
                }
                
                public void removeUpdate(DocumentEvent e)
                {
                	 countText();
           
                }
                
                public void changedUpdate(DocumentEvent e)
                {
                	 countText();
              	  
                }
            });


...

private void countText() {

	Runnable cutText = new Runnable() {
	
		@Override
	public void run() {
    	
		if(content.getDocument().getLength() > MAX_LEN){
        	
			try {
				content.getDocument().remove(MAX_LEN, (content.getDocument().getLength()) - MAX_LEN);  
      		
      				} catch (BadLocationException ex) {
				ex.printStackTrace();
			}
      			}else {

		}	
	}
};

SwingUtilities.invokeLater(cutText);
}

@schmitt19 Bitte, wenn möglich, immer vollständige Codebeispiele bringen (dann haben andere auch etwas davon):

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class MyTextArea {
    private static final int MAX_CHARS = 50;

    private static void checkMaxChars(JTextArea area, KeyEvent e) {
        if (area.getText().length() > MAX_CHARS) {
            // optional:
            if (e != null) {
                e.consume();
            }

            StringBuilder b = new StringBuilder(area.getText());
            while (b.length() > MAX_CHARS) {
                b.deleteCharAt(b.length() - 1);
            }
            SwingUtilities.invokeLater(() -> {
                int caret = Math.min(area.getCaretPosition(), MAX_CHARS);
                area.setText(b.toString());
                area.setCaretPosition(caret);
            });
        }
    }

    public static void main(String[] args) {
        JTextArea area = new JTextArea("Es sind max. " + MAX_CHARS + " Zeichen erlaubt.");
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(area));
        frame.setSize(500, 200);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setVisible(true);

        area.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
                checkMaxChars(area, e);
            }

            @Override
            public void keyPressed(KeyEvent e) {
                checkMaxChars(area, e);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                checkMaxChars(area, e);
            }
        });
        area.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                checkMaxChars(area, null);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                checkMaxChars(area, null);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                checkMaxChars(area, null);
            }
        });
    }
}

Ani1

Verzeiht das Doppelposting. Eigentlich braucht man nur den DocumentListener.