JTextField, DocumentListener, Fehler bei setText()

Goldi

Aktives Mitglied
Hi Leute,

ich möchte gerne die Swing-Kompenenten für mich etwas erweitern, z. B. mit einem Textfeld, das nur für Zahlen vorgesehen ist und andere Ziffern gar nicht erst zulässt. Ich dachte mir also: :idea: Melde ich einen DocumentListener an, prüfe nach jedem mal Tippen über die Methode
Code:
insertUpdate
des Listeners, ob das Feld noch eine gültige Zahl ist und falls nicht, wird das zuletzt eingetippte Zeichen (das muss ja der Übeltäter sein) einfach wieder gelöscht und die CurretPosition um 1 zurück gesetzt.

Der Mist ist :shock::
Java:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
	at javax.swing.text.AbstractDocument.writeLock(Unknown Source)
	at javax.swing.text.AbstractDocument.replace(Unknown Source)
	at javax.swing.text.JTextComponent.setText(Unknown Source)
	at GoldisSwing.BspJTextField.insertUpdate(BspJTextField.java:19)
        ... (da kommt noch viel mehr) ...

Das Problem scheint wohl zu sein, dass der Konflikt der setText-Methode damit zusammenhängt, dass sie innerhalb der insertUpdate-Methode aufgerufen wird. Natürlich hab ich recherchiert und etwas (leider nicht viel) über eine Methode "invokeLater" erfahren, die aufgerufen werden müsse und über eine EventQueue-Klasse. Ich habe versucht, mich in meinen Büchern und auf den einschlägigen Seiten und auch hier im Forum darüber zu informieren. Aber in deutscher Sprache ist die Info dazu eher rar und mit meinem awful English habe ich nicht so viel kapiert, dass ich es anwenden könnte. Hiiiiilfeeeee!!

Ich will Euch nicht mit meinem ellenlangen Code die Zeit stehlen, deshalb hier ein sehr kleines Beispiel als Quintessenz. Es ist zwar vom Ergebnis her unsinnig, aber entscheidend ist: Die setText-Methode innerhalb der insertUpdate-Methode schlägt mit obiger Meldung fehl. Übrigens: Listener abmelden, Text ändern und Listener wieder anmelden bringt keine Besserung. Was muss ich tun, damit das funzt?

Java:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;

public class BspJTextField extends JTextField implements DocumentListener {

	public BspJTextField(int columns) {
		super(columns);
		getDocument().addDocumentListener(this);
	}

	@Override
	public void insertUpdate(DocumentEvent e) {
		/* Sobald etwas in das Textfeld getippt wird, wird der Textinhalt einfach
		 * ein 2. Mal hinten angehängt: */
		String inhalt = getText();
		setText(inhalt + inhalt);
	}
	
	
	// Nicht benötigte Methoden aus DocumentListener:
	@Override
	public void changedUpdate(DocumentEvent e) {}

	@Override
	public void removeUpdate(DocumentEvent e) {}
}

Vielen Dank schon mal im Voraus.

Gruß
Goldi
 
Hi Leute,

ich möchte gerne die Swing-Kompenenten für mich etwas erweitern, z. B. mit einem Textfeld, das nur für Zahlen vorgesehen ist und andere Ziffern gar nicht erst zulässt.

Da könntest du z.B. einen DocumentFilter nutzen, ein Beispiel (Pattern anpassen) ist hier zu finden: http://www.java-forum.org/bilder-gu...7213-jtextfield-dokumentarten.html#post587501


p.s.: Mit invokeLater hat dein Problem nichts zu tun. Du solltest dir, wenn es dich interessiert, mal ein wenig auf Text Component Features (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components) einlesen. Eine Textkomponenten, oder generell Swingkomponenten besitzen eine View und ein Model (Document). Du bist hier schon auf der Ebene des Models / Documents und willst dieses nun in der insertUpdate ändern, rufst nun aber wieder eine Methode der View/Controllers auf um das Document zu ändern...macht keinen Sinn und würde nur zu einer Endlosschleife führen!
 
Servus Basti,

ich hab's zwar nicht auf Anhieb hingekriegt ;(, aber mit einigem Lesen und Probieren: Hat geklappt :applaus:. Danke für die richtige Wegweisung (weg vom Holzweg 😀).

Besten Gruß
Goldi
 
Peinlich, peinlich, ich hab die Tage einen neuen Thread zum gleichen Thema aufgemacht. Dass ich vor gut einem Jahr schon mal um Hilfe gebeten habe ... ich werde alt!!! ;( Also tschuldigung, an alle, die das nervt. Ich kann mich auch an die Lösung nicht mehr erinnern ... jetzt hab ich aber eine, die wesentlich einfacher geht als der DocumentListener. für alle die's interessiert (und für mich in ca. 1 Jahr 😳):

Man nehme den UndoableEditListener!

Klassendefinition:
Code:
public class xyz
extends JTextField
implements UndoableEditListener

Konstruktur:
Code:
public xyz() {
		...
		getDocument().addUndoableEditListener(this);
	}

Ereignismethode:
Code:
/* Wenn das ganze Textfeld ungültig ist (z. B. nicht numerisch für Zahlenfelder), 
 * muss das letzte eingetippte Zeichen dazu geführt haben: */
public void undoableEditHappened(UndoableEditEvent e) {
	String inhalt = getText();
	if (<inhalt erfüllt nicht die Gültigkeitsregeln>)
			e.getEdit().undo();
	}

Gruß
Goldi
 

Zurück
Oben