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

Verzeiht das Doppelposting. Eigentlich braucht man nur den DocumentListener
.