Formatter für Formularblatt - reguläre Ausdrücke

Chriss_07

Aktives Mitglied
Ich habe mit SWT ein Formularblatt erstellt, in dem Textfelder mittels regulären Ausdrücken definiert werden soll. Dazu habe ich mir bereits ein snippet von SWT angesehen, weiß aber noch nicht so ganz wie ich das umsetzten kann.
Ein Textfeld soll für die Telefonnummer sein und der Text folgenden Kriterien entsprechen: +49.####-######
Ein weiteres ist für eine Referenznummer: UUU### also drei Buchstaben (Uppercase) und drei Zahlen.
Java:
text.setText(template); // das Template ist die Vorlage (UUU###)	
	text.addListener(SWT.Verify, new Listener() {
		//create the pattern for verification
		Pattern pattern = Pattern.compile(REGEX);   // REGEX gibt die Syntax vor ([+49.]\\d{4}[-]\\d{4])
...
...
		public void handleEvent(Event e) {
.....
.....
Das finde ich super, denn so kann ich für jedes textfeld ein REGEX1, REGEX2, Template1, Template2 erstellen und muss nur noch das jeweilige Event am textfeld auslösen. Nur weiß ich nicht wie???:L
Hat da jemand ne helfende Hand??
 
Damit begrenze ich aber nicht die Eingabe. Ich möchte ja an bestimmten Stellen nur Zahlen eingeben können und das auch nur in bestimmter Anzahl. Bei der Referenznummer möchte ich drei Buchstaben und dann Zahlen eingeben können. Da helfen mir nur reguläre Ausdrücke weiter aber ich weiß nicht wie ich das anstellen soll. Toll finde ich halt die Verifizeirung über reguläre Ausdrücke. Da bräuchte ich Hilfe, um das auf meine Masken anzuwenden.
 
Sicher kannst du es.
Du kannst mit:
Java:
String s = e.text;
if (!s.matches(regex)) {
  e.doit = false;
}
versuchen (
Code:
e
ist eben dein Event)
 
Ja genau, ich habe das an dem Kurzen kompilierbaren Beispiel ausprobiert, indem ich meine Telefonvorlage eingebunden habe aber da kann ich nichts eingeben und beim löschen wird mir die +49 mitgelöscht:
Java:
import java.util.regex.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class Snippet196 {

	private static final String REGEX = "[+49.]\\d{4}[-]\\d{6}";  //$NON-NLS-1$
	private static final String template = "+49.####-######"; //$NON-NLS-1$
	private static final String defaultText = "+49.0000-000000"; //$NON-NLS-1$
	
	
public static void main(String[] args) {
	
	Display display = new Display();
	Shell shell = new Shell(display);
	shell.setLayout(new GridLayout());
	final Text text = new Text(shell, SWT.BORDER);
	Font font = new Font(display, "Courier New", 10, SWT.NONE); //$NON-NLS-1$
	text.setFont(font);
	text.setText(template);	
	text.addListener(SWT.Verify, new Listener() {
		//create the pattern for verification
		Pattern pattern = Pattern.compile(REGEX);	
		//ignore event when caused by inserting text inside event handler
		boolean ignore;
		public void handleEvent(Event e) {
			if (ignore) return;
			e.doit = false;
			if (e.start > 14|| e.end > 15) return;
			StringBuffer buffer = new StringBuffer(e.text);
			
			//handle backspace
			if (e.character == '\b') {
				for (int i = e.start; i < e.end; i++) {
					// skip over separators
					switch (i) {
						case 0: 
							if (e.start + 1 == e.end) {
								return;
							} else {
								buffer.append('.');
							}
							break;
						case 4:
							if (e.start + 1 == e.end) {
								buffer.append(new char [] {'#','-'});
								e.start--;
							} else {
								buffer.append('-');
							}
							break;
						default: buffer.append('#');
				}
				text.setSelection(e.start, e.start + buffer.length());
				ignore = true;
				text.insert(buffer.toString());
				ignore = false;
				// move cursor backwards over separators
				if (e.start == 4 || e.start == 9) e.start--;
				text.setSelection(e.start, e.start);
				return;
			}
			
			StringBuffer newText = new StringBuffer(defaultText);
			char[] chars = e.text.toCharArray();
			int index = e.start - 1;
			for (int i = 0; i < e.text.length(); i++) {
				index++;
				switch (index) {
					case 0:
						if (chars[i] == '.') continue;
						index++;
						break;
					case 4:
						if (chars[i] == '-') continue;
						index++;
						break;
				}
				if (index >= newText.length()) return;
				newText.setCharAt(index, chars[i]);
			}
			// if text is selected, do not paste beyond range of selection
			if (e.start < e.end && index + 1 != e.end) return;
			Matcher matcher = pattern.matcher(newText);
			if (matcher.lookingAt()) {
				text.setSelection(e.start, index + 1);
				ignore = true;
				text.insert(newText.substring(e.start, index + 1));
				ignore = false;
			}			
		}
		}
	});
		
	shell.pack();
	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch())
			display.sleep();
	}
	font.dispose();
	display.dispose();
}
}

Kannst du mir das vllt im Detail erklären, was ich da genau falsch mache?
Gruß Chriss
 
Also wenn ich die +49 als ### mit übergebe, dann funktioniert das, allerdings will ich ja diese vorgeben und nicht zulassen diese zu editieren. Wie gibt man die +49 als festen Wert vor?
 
Naja, um solche Scherze bei der Eingabe zu machen, musst du natürlich aufpassen, z.B.:
du sollst 5 Zeichen eingeben.
Wenn ich anfange "123" zu tippen (und will schließend "45" dazumachen), dann ist es ja in dem Moment kein zugelassener String.
Mein Vorschlag wäre das ganze mit einem FocusListener zu machen, denn nach der Eingabe, musst du ja irgendwas machen, sprich Focus verlieren.
Du könntest ja sowas wie:
Java:
private class ValidateFocusListener implements FocusListener{
	private String pattern = "";
	private String defaultValue = "";
	public ValidateFocusListener(String defaultValue, String pattern) {
		this.defaultValue = defaultValue;
		this.pattern = pattern;
	}
	@Override
	public void focusGained(FocusEvent e) {}

	@Override
	public void focusLost(FocusEvent e) {
		if (e.getSource() instanceof JTextField) {
			JTextField field = (JTextField) e.getSource();
			if (!field.getText().matches(pattern)) {
				field.setText(defaultValue);
			}
		}
	}
}
machen
 
Dann schreib das Bsp auch in SWT und nicht in Swing... In Swing würde ich nämlich für so ein Problem eher einen setInputVerifier benützen...

Und in SWT würde ich ein VerifyListener oder ein ModifyListener verwenden
SWT Snippets und da suchst du "verify input using a regular expression"...
oder eben die nebula widgets und dafür einen eigenen RegexFormatter ist wesentlich einfacher...
Aber für deine Zwecke müsste der MaskFormatter doch schon alles mitbringen...
 
Zuletzt bearbeitet von einem Moderator:
JA das mit dem Nebula MaskFormatter hatte ich mir auch einfach vorgestellt aber Letters werden auch mit Digist interpretiert und das stört mich. ALso sind bei einem MaskFormattet String UUU### auch nur Zahlen möglich, hingegen wird ein Digist String korrekt dargestellt und lässt keine Letters zu.:bahnhof:
Scheint wohl ein Nebula Bug zu sein
 
Mach ein Beispiel weiß nicht ob ich dich richtig verstanden habe...

Aber kannst ja mal ein bug melden ich denke U und L sollten keine Numbers zu lassen und A auch nicht...

Aber wie gesagt kannst dir ja auch einen eigenen Formatter schreiben muss mal daheim schauen ob ich ein Bsp. hab.

EDIT:
So ist es implementiert...
Java:
  case P_UPPERCASE :
176	          if ( Character.isLetterOrDigit(c) ) {
177	            editValue.setCharAt(i, Character.toUpperCase(c));
178	          } else {
179	            throw new IllegalArgumentException(INVALID_VALUE);
180	          }
181	          break;
182	        case P_LOWERCASE :
183	          if ( Character.isLetterOrDigit(c) ) {
184	            editValue.setCharAt(i, Character.toLowerCase(c));
185	          } else {
186	            throw new IllegalArgumentException(INVALID_VALUE);
187	          }
188	          break;
189	        case P_ALPHANUM :
190	          if ( Character.isLetterOrDigit(c) ) {
191	            editValue.setCharAt(i, c);
192	          } else {
193	            throw new IllegalArgumentException(INVALID_VALUE);
194	          }
195	          break;
196	        default :
 
Zuletzt bearbeitet von einem Moderator:
Hier nimmst halt den so lang 😉 sollte doch deinen Vorstellung entsprechen wenn nicht kannst dir wie gesagt einen eigenen schmieden...
Java:
	static class  MyMaskFormatter extends MaskFormatter{
		  private static final char P_DIGIT = '#';
		  private static final char P_ALPHANUM = 'A';
		  private static final char P_UPPERCASE = 'U';
		  private static final char P_LOWERCASE = 'L';
		  private static final String INVALID_VALUE = "Wrong Value";
		  
		public MyMaskFormatter(String editPattern) {
			super(editPattern);
		}
		
		protected int insertText(String txt, int start) {
				    int i = start, j = 0;
				    char p, c, o;
				
				    while ( i < editPattern.length() && j < txt.length() ) {
				      p = editPattern.charAt(i);
				      c = txt.charAt(j);
				      o = editValue.charAt(i);
				      switch ( p ) {
				        case P_DIGIT :
				          if ( Character.isDigit(c) ) {
				            editValue.setCharAt(i, c);
				          } else {
				            throw new IllegalArgumentException(INVALID_VALUE);
				          }
				          break;
				        case P_UPPERCASE :
				          if ( Character.isLetter(c) ) {
				            editValue.setCharAt(i, Character.toUpperCase(c));
				          } else {
				            throw new IllegalArgumentException(INVALID_VALUE);
				          }
				          break;
				        case P_LOWERCASE :
				          if ( Character.isLetter(c) ) {
				            editValue.setCharAt(i, Character.toLowerCase(c));
				          } else {
				            throw new IllegalArgumentException(INVALID_VALUE);
				          }
				          break;
				        case P_ALPHANUM :
				          if ( Character.isLetter(c) ) {
				            editValue.setCharAt(i, c);
				          } else {
				            throw new IllegalArgumentException(INVALID_VALUE);
				          }
				          break;
				        default :   // Separator
				          if ( p != c ) {
				            if ( Character.isLetterOrDigit(c) ) {
				              i++;
				              continue;
				            } else {
				              throw new IllegalArgumentException(INVALID_VALUE);
				            }
				          }
				          o = '*';
				          break;
				      }
				      if ( o == SPACE && c != SPACE ) {
				        count++;
				      }
				      i++;
				      j++;
				    }
				    return i;
				  }
	}
 
Danke, werde ich mir anschauen wenn ich zu HAus bin.
SO hatte ich den Nebula implementiert
Java:
							refnr.getControl().setEditable(true);
							MaskFormatter tpn = new MaskFormatter("UUU###");
							refnr.setFormatter(tpn);
							refnr.getControl().setTextLimit(8);

Wobei angemerkt, das ganze über ein Combo Press funktioniert, also in etwas so:

Java:
if (value.equals("Referenznummer")) {
							MaskFormatter pn = new MaskFormatter("UUU###");
							refnr.setFormatter(pn);
							refnr.getControl().setEditable(true);
							refnr.getControl().setTextLimit(12);
							if (textProcessNo.getControl().getText().equals("0"))
								textProcessNo.getControl().setText("");
						}
						if (value.equals("telnummer")) {
							telnr.getControl().setText("");
							NumberFormatter nf = new NumberFormatter("######");
							telnr.setFormatter(nf);
							telnr.getControl().setEditable(true);
							telnr.getControl().setTextLimit(6);
							if (telnr.getControl().getText().equals("0"))
								telnr.getControl().setText("");

Ich glaube so in etwa habe ich das versucht und da erzeugt der Nebula MaskFormatter falsche Eingabemöglichkeiten für "UPPERCASE".
 
Was heißt flasche Eingabemöglichkeiten???

In nebula MaskFormatter lässt UPPERCASE und LOWERCASE zahlen siehst du doch im oben geposteten Code. Deshalb kannst du einen eigenen Formatter schreiben der dies nicht zu lässt siehe mein Bsp.
 
ICh dachte

U = Any character (Character.isLetter). All lowercase letters are mapped to upper case
# = Any valid number, uses Character.isDigit.

Wenn U und L auch DIgit zulassen, nehm ich das mit dem Bug zurück, finde es aber trotzdem unpassend.
 
ICh dachte

U = Any character (Character.isLetter). All lowercase letters are mapped to upper case
# = Any valid number, uses Character.isDigit.

Wenn U und L auch DIgit zulassen, nehm ich das mit dem Bug zurück, finde es aber trotzdem unpassend.

Steht ja nirgends^^... Also ich hab keine Beschreibung zu dem Formatter gefunden...
Aber wie gesagt mit dem Formatted Text widget kann man ja einen eigenen schreiben ohne großen Aufwand... Kannst ja sogar noch ein wildcard einführen wo beides erlaubt sein soll B oder so^^
 

Zurück
Oben