# DocumentListener soll Text in JTextField ändern



## RawBit (24. Okt 2012)

Hallo,

bin gerade auf folgendes Problem gestoßen:

Ich bin dabei eine kleine Komponente zu schreiben, die ein Eingabefeld für IP Adressen darstellen soll

Ich prüfe mit dem DocumentListener ob die Eingabe der Zahl (es werden nur Zahlen zugelassen, bei der Eingabe) 255 nicht überschreitet.


```
columns[i].getDocument().addDocumentListener(new DocumentListener(){
                public void insertUpdate(DocumentEvent e) {
                    try {
                        if(Integer.parseInt(e.getDocument().getText(0, e.getDocument().getLength())) > 255) {
                            e.getDocument().remove(0, e.getDocument().getLength());
                            e.getDocument().insertString(0, "255", null);
                        }
                    } catch( BadLocationException ble ) { }
                }
                public void removeUpdate(DocumentEvent e) {
                }
                public void changedUpdate(DocumentEvent e) {
                }
            });
```

Dabei werfen die Zeilen

```
e.getDocument().remove(0, e.getDocument().getLength());
e.getDocument().insertString(0, "255", null);
```
eine Exception:

[WR]Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
	at javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1338)
	at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:585)
	at ordermax.JIPTextField$2.insertUpdate(JIPTextField.java:48)
	at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:202)
	at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)
	at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:708)
	at javax.swing.text.PlainDocument.insertString(PlainDocument.java:130)
	at ordermax.JIPTextField$1.insertString(JIPTextField.java:35)
	at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:670)
	at javax.swing.text.JTextComponent.replaceSelection(JTextComponent.java:1379)
	at javax.swing.text.DefaultEditorKit$DefaultKeyTypedAction.actionPerformed(DefaultEditorKit.java:884)
	at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1664)
	at javax.swing.JComponent.processKeyBinding(JComponent.java:2879)
	at javax.swing.JComponent.processKeyBindings(JComponent.java:2926)
	at javax.swing.JComponent.processKeyEvent(JComponent.java:2842)
	at java.awt.Component.processEvent(Component.java:6282)
	at java.awt.Container.processEvent(Container.java:2229)
	at java.awt.Component.dispatchEventImpl(Component.java:4861)
	at java.awt.Container.dispatchEventImpl(Container.java:2287)
	at java.awt.Component.dispatchEvent(Component.java:4687)
	at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)
	at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:762)
	at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1027)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:899)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:727)
	at java.awt.Component.dispatchEventImpl(Component.java:4731)
	at java.awt.Container.dispatchEventImpl(Container.java:2287)
	at java.awt.Window.dispatchEventImpl(Window.java:2719)
	at java.awt.Component.dispatchEvent(Component.java:4687)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:723)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:682)
	at java.awt.EventQueue$3.run(EventQueue.java:680)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
	at java.awt.EventQueue$4.run(EventQueue.java:696)
	at java.awt.EventQueue$4.run(EventQueue.java:694)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:693)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)[/WR]

Nach ein paar Recherchen hab ich festgestellt, daß der Inhalt wohl vom DocumentListener nicht bearbeitet werden darf und dazu irgendein vages Gebrabbel (noch dazu in Englisch...), daß man ein eigenes Document schreiben und insertString() und remove() überschreiben soll.

Mal abgesehen davon, daß ich den DocumentListener wegen seiner ganzen sinnlosen Kompliziertheit und Unlogik verabscheue frage ich mich, wie ich das hinkriegen soll ?

Jemand mehr Erfahrungen mit dem DocumentListener als ich ?

Lg


----------



## KSG9|sebastian (24. Okt 2012)

Sowas hier ist gemeint:


```
JTextArea area = new JTextArea(10, 100);
        area.setDocument(new PlainDocument() {
            @Override
            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
                try {
                    Integer.parseInt(str);
                    // integer - insert ok
                    super.insertString(offs, str, a);
                } catch (NumberFormatException nfe) {
                    // no number, reject insert
                }
            }
        });
```
Anstatt eines Listeners kannst du die Prüfungen direkt im Document erledigen.
Obiges Beispiel erlaubt nur die Eingabe von Zahlen..damit kannst du das Problem bestimmt lösen.

Andere Möglichkeit (habe ich nicht Probiert) wäre über den DocumentFilter..

siehe [JAPI]javax.swing.text.AbstractDocument[/JAPI] bzw [JAPI]javax.swing.text.DocumentFilter[/JAPI]


----------



## RawBit (24. Okt 2012)

Leider nicht - die Überprüfung auf Zahlen hab ich schon - es geht ja darum ob die Zahl <= 255 ist - ich hab schon super.getText(0,3); versucht um den gesamten Inhalt des Feldes zu bekommen, aber das funktioniert genauso wenig...


----------



## Melfis (24. Okt 2012)

Wenn du schon kontrollierst ob die eingabe eine Zahl ist, wieso kontrolierst du nicht an selber stelle den Wert dieser Zahl? Beispiel:


```
public class IPDocument extends PlainDocument
{
   public void insertString(int offset, String s, AttributeSet attributeSet) throws BadLocationException
    {
      int i;
      boolean ok=true;

      try{
             i=Integer.parseInt(s);
         }
         catch(Exception ex)   //only allow integer values
         {
         ok=false;
         }
      if(i<0||i>255)ok=false;
      if(!ok){
            Toolkit.getDefaultToolkit().beep();
            return ;
      }
      super.insertString(offset,s, attributeSet);
    }
}
```

Würde aber einen InputVerifier empfehlen, ist für den Nutzer der Eingabe angenehmer. 

MFG Melfis


----------



## KrokoDiehl (25. Okt 2012)

Du kannst dir auch mal ein JFormattedTextField anschauen. In einem Listener zu ändern ist der falsche Ansatz und könnte schlimmstenfalls zu einem Endlosaufruf führen (... naja, z.G. kommt die Exception ;-)).

Ansonsten gibt es InputVerifier oder eben doch ein eigenes Dokument.


----------

