Swing Autokorrektur der Texteingabe

Basti90

Mitglied
Hallo zusammen,

Ich möchte eine überprüfung von 2 Textfeldern machen
alle Editierbar, es sollen nur Zahlen zulässig sein(Aber vernachlässigbar nur zum verständnis). Da aus den ersten Zwei Zahlen die dritte berechnet werden soll (und einer weiteren Zahl), die Differenz aus aus behalterinhalt und gegMenge darf nicht kleiner 0 werden wenn doch soll der Alte wert von gegeMenge eingetragen werden.
Ich hab die eingabeüberprüfung mit DocumentListener gelöst - leider ist es da nicht möglich eine Korrektur eines Feldes vorzunehmen da sonst ein IllegalStateException fliegt.(in Zeile 74 würde die Exception Fliegen)




Java:
JTextField Textrestmenge=new JTextField();
JTextField Text
Textrestmenge().getDocument().addDocumentListener(new DocumentListener() {
				
 				 @Override
				   public void removeUpdate(DocumentEvent arg0) {
					
					
				  }
				
				 @Override
				     public void insertUpdate(DocumentEvent arg0) {
					   checkrestmenge();
					
				 }
				
 				 @Override
				  public void changedUpdate(DocumentEvent arg0) {
					  checkrestmenge();
					
				}
				private void checkrestmenge(){
 					if(isNumeric(Textrestmenge().getText())){
						cont.pruefeBehaltervoll();
					 }
					 else{
						 new Fehlermeldung(frame, "Es wurde Keine Zahl eingegeben, es   sind nur Zahlen zulässig!");
 						restmenge().setText(String.valueOf(restmenge));;
					}
				}
			});
Textgegmeng().getDocument().addDocumentListener(new DocumentListener() {
				
				 @Override
  				public void removeUpdate(DocumentEvent arg0) {
					
					
				 }
				
				@Override
				   public void insertUpdate(DocumentEvent arg0) {
				
 					checkgegmenge();
					
				 }
				
				@Override
				 public void changedUpdate(DocumentEvent arg0) {
					
 					checkgegmenge();
				 }
				private void checkgegmenge(){
					 if(isNumeric(Textgegmeng().getText())){
						cont.pruefeBehaltervoll();
					 }
					else{
						 new Fehlermeldung(frame, "Es wurde Keine Zahl eingegeben, es   sind nur Zahlen zulässig!");
						
					}
 					berechneRestmengeNeu();
					
 				}

				
});
			

public void berechneRestmengeNeu(){
		if((!Textgegmeng().getText().equals(""))&&(!Textrestmenge().getText().equals(""))){
			restmenge=behalterinhalt-Integer.valueOf(Textgegmeng().getText());
			if(restmenge<0){
				if(bildschirmtastaturmodus){
				JOptionPane.showMessageDialog(frame, "Die Restmenge kann nicht negativ sein!","Warnung",JOptionPane.INFORMATION_MESSAGE);
                                  setTextgegmeng().setText(String.valueOf(altgegmenge));
				}
			}
			else{
				Textrestmenge().setText(String.valueOf(restmenge));
				
			}
		}
	}



Gibts nen anderen weg die Felder bei der Eingabe zu überprüfen? oder kann man doch mit dem Documentlistener die Werte ändern?

Vielen dank für die Antworten im Vorraus
 

Flown

Administrator
Mitarbeiter
Ahja da hat mans wieder, wenn man in die API, nämlich HIER, reinsieht ist gleich zu Anfang dein Problem gelöst!

Aber für die faulen Menschen:
Java:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;

public class TextFieldTutorial {
	
	public static void main(String[] args) {
		new TextFieldTutorial();
	}
	
	public TextFieldTutorial() {
		JFrame frame = new JFrame("TextFields");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationByPlatform(true);
		
		JPanel mainPanel = new JPanel();
		NumericTextField ntf1 = new NumericTextField(10);
		NumericTextField ntf2 = new NumericTextField(10);
		
		mainPanel.add(ntf1);
		mainPanel.add(ntf2);
		
		frame.add(mainPanel);
		frame.pack();
		frame.setVisible(true);
	}
	
	class NumericTextField extends JTextField {
		private static final long serialVersionUID = 1L;
		
		public NumericTextField(int col) {
			super(col);
		}
	 
	     protected Document createDefaultModel() {
	         return new NumericDocument();
	     }
	 
	     class NumericDocument extends PlainDocument {
			private static final long serialVersionUID = 1L;

			public void insertString(int offs, String str, AttributeSet a)
	             throws BadLocationException {
	 
	             if (str == null) {
	                 return;
	             }
	             StringBuilder sb = new StringBuilder();
	             for(char c : str.toCharArray()) {
	            	 if(Character.isDigit(c)) {
	            		 sb.append(c);
	            	 }
	             }
	             super.insertString(offs, sb.toString(), a);
	         }
	     }
	}
}
 
Zuletzt bearbeitet:

Basti90

Mitglied
So schnell kann man sich Irren-
Ich bekomme beim eintragen der alten Werte wieder eine Excpetion
Intressanter weiße tritt der Fehler erst im Zweiten fenster auf
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.remove(Unknown Source)
at GUI.Test.berechneRestmengeNeu(Test.java:13)....

Java:
public static void berechneRestmengeNeu(){
	if((!Textgegmeng().getText().equals(""))&&(!Textbesteil().getText().equals(""))&&(!Textrestmenge().getText().equals(""))){
		restmenge=behalterinhalt-Integer.valueOf(Textbesteil().getText())-Integer.valueOf(Textgegmeng().getText());
		if(restmenge<0){
// test ob die Felder leer sind wenn nicht findet keine Berechnung statt			
			
				JOptionPane.showMessageDialog(frame, "Die Restmenge kann nicht negativ sein!","Warnung",JOptionPane.INFORMATION_MESSAGE);
			}
			try {
//sollten der wert kleiner 0 sein werden die werte auf den alten Stand zurückgesetzt bevor die //änderung war
Textrestmenge().getDocument().remove(0,Textrestmenge().getDocument().getLength());
				Textrestmenge().getDocument().insertString(0, String.valueOf(vorchgrestmenge), null);
				Textgegmeng().getDocument().remove(0, Textgegmeng().getDocument().getLength());
				Textgegmeng().getDocument().insertString(0, String.valueOf(vorchggreifmenge), null);
				Textbesteil().getDocument().remove(0, Textbesteil().getDocument().getLength());
				Textbesteil().getDocument().insertString(0, String.valueOf(vorchgbeschTeile), null);
			} catch (BadLocationException e) {
				
				e.printStackTrace();
			}
		}
		else{//wenn wert ok wert in Gui eintragen und die Voränderungswerte aktualisieren
			Textrestmenge().setText(String.valueOf(restmenge));
			vorchgrestmenge=restmenge;
			vorchgbeschTeile=Integer.valueOf(Textbesteil().getText());
			vorchggreifmenge=Integer.valueOf(Textgegmeng().getText());
		}
	}
}

Die frage ist nachwie vor wie kann ich direkt nach der eingabe den wert ändern - so offensichtlich nicht- oder was mach ich falsch?
 

Basti90

Mitglied
ok ich hab jetz die lösung.
Beim Schreiben wird durch den Documentlistener das Feld zum schreiben gelocked - darum geht auch das löschen nicht - man kann das ganze mit einem Thread umgehen.

hier meine Lösung für alle die das gleiche problem haben:

Java:
Runnable entfernealteneintrag=new Runnable() {
		
		@Override
		public void run() {
			try{
				Textrestmenge().getDocument().remove(0,  Textrestmenge().getDocument().getLength());
				

				Textrestmenge().getDocument().insertString(0, String.valueOf(vorchgrestmenge), null);
				
				Textgegmeng().getDocument().remove(0,   Textgegmeng().getDocument().getLength());
				Textgegmeng().getDocument().insertString(0, String.valueOf(vorchggreifmenge), null);
				
				Textbesteil().getDocument().remove(0, Textbesteil().getDocument().getLength());
				Textbesteil().getDocument().insertString(0, String.valueOf(vorchgbeschTeile), null);
			
			}catch(BadLocationException e){
	            e.printStackTrace();
	        }
			
		}
	};
	

	/**
	 * Berechnet die Restmenge neu aus Behälterinhalt beschädigte Teile und Gegriffene Menge
	 */
	public void berechneRestmengeNeu(){
		if((!Textgegmeng().getText().equals(""))&&(!Textbesteil().getText().equals(""))&&(!Textrestmenge().getText().equals(""))){
			//Prüfe ob die Felder leer sind wenn ja findet keine Berechung statt
			restmenge=behalterinhalt-Integer.valueOf(Textbesteil().getText())-Integer.valueOf(Textgegmeng().getText());
			if(restmenge<0){
				//Prüfen was das oberste Frame im moment ist für die Anzeige der Fehlermeldung an oberster Stelle
				
					JOptionPane.showMessageDialog(frame, "Die Restmenge kann nicht negativ sein!","Warnung",JOptionPane.INFORMATION_MESSAGE);
				
					//Startet Thread zum Löschen der Falschen werte und ersetzen durch neue Thread notwendig da sonst ein Lock zum schreiben auf das feld ist 
					SwingUtilities.invokeLater(entfernealteneintrag);

					
				
			}
			else{
				Textrestmenge().setText(String.valueOf(restmenge));
				vorchgrestmenge=restmenge;
				vorchgbeschTeile=Integer.valueOf(Textbesteil().getText());
				vorchggreifmenge=Integer.valueOf(Textgegmeng().getText());
			}
		}
	}
 

Goldi

Aktives Mitglied
Falls es noch jemandem hilft: Viel einfacher ist der 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
 

Ähnliche Java Themen


Oben