problem with NumberFormatted Factory in Java swings - java

I use a jFormattedTextField for a telephone number and only to accept the numeric values i
declare it as "new NumberFormatterFactory(Integer.class, false)" .
Now the problem is when the number starts with 0(zero) like 001345.. , after entered the value and moved to next column the entered value is trimmed as 1345.. here it not accepting the 0 as the starting number.
how can I enter the number starts with 0

Yeah, telephone numbers are slightly different from integers in that sense.
Following this example at you could solve it using regular expressions like this:
import java.text.ParseException;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.text.DefaultFormatter;
class RegexFormatter extends DefaultFormatter {
private Pattern pattern;
private Matcher matcher;
public RegexFormatter() {
super();
}
public RegexFormatter(String pattern) throws PatternSyntaxException {
this();
setPattern(Pattern.compile(pattern));
}
public RegexFormatter(Pattern pattern) {
this();
setPattern(pattern);
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
public Pattern getPattern() {
return pattern;
}
protected void setMatcher(Matcher matcher) {
this.matcher = matcher;
}
protected Matcher getMatcher() {
return matcher;
}
public Object stringToValue(String text) throws ParseException {
Pattern pattern = getPattern();
if (pattern != null) {
Matcher matcher = pattern.matcher(text);
if (matcher.matches()) {
setMatcher(matcher);
return super.stringToValue(text);
}
throw new ParseException("Pattern did not match", 0);
}
return text;
}
}
public class Test {
public static void main(String[] a) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFormattedTextField formattedField =
new JFormattedTextField(new RegexFormatter("\\d*"));
frame.add(formattedField, "North");
frame.add(new JTextField(), "South");
frame.setSize(300, 200);
frame.setVisible(true);
}
}

If you declare it as new NumberFormatterFactory(Integer.class, false) which is for only Integer, 0 wont be considered. You need to change it to other formatter and not store Phone Number as number (i.e. Integer).
Check this example for phone number formatting:
http://www.java2s.com/Code/Java/Swing-JFC/JFormattedTextFieldaninputmaskforatelephonenumber.htm
http://www.ibm.com/developerworks/java/library/j-mer0625/index.html

Related

How to get class level variable names using javaparser?

I was able to get class level variable's declarations using the following code. But I only need the variable name. This is the output I get for following code - [private boolean flag = true;]
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import java.io.FileInputStream;
public class CuPrinter{
public static void main(String[] args) throws Exception {
// creates an input stream for the file to be parsed
FileInputStream in = new FileInputStream("C:\\Users\\arosh\\IdeaProjects\\Bot_Twitter\\src\\MyBot.java");
CompilationUnit cu;
try {
// parse the file
cu = JavaParser.parse(in);
} finally {
in.close();
}
cu.accept(new ClassVisitor(), null);
}
private static class ClassVisitor extends VoidVisitorAdapter<Void> {
#Override
public void visit(ClassOrInterfaceDeclaration n, Void arg) {
/* here you can access the attributes of the method.
this method will be called for all methods in this
CompilationUnit, including inner class methods */
System.out.println(n.getFields());
super.visit(n, arg);
}
}
}
You can use the following simple regex:
final String regex = "^((private|public|protected)?\\s+)?.*\\s+(\\w+);$";
Which then can be compiled into a Pattern:
final Pattern pattern = Pattern.compile(regex);
And then finally be used in a for-loop:
for(final String field : n.getFields()){
// create a regex-matcher
final Matcher matcher = pattern.matcher(field);
// if field matches regex
if(matcher.matches()){
// get the last group -> the fieldName
final String name = matcher.group(matcher.groupCount());
System.out.println("FieldName: " + name);
}
}
You can try this. If you have more than one variables in FieldDeclarations, use one more for loop inside.
public void visit(ClassOrInterfaceDeclaration n, Void arg) {
super.visit(n, arg);
for(FieldDeclaration ff:n.getFields())
{
System.out.println(ff.getVariable(0).getName());
}
}

REGEX matcher any/all groups

while (matcher.find()) {
if (matcher.group(matcherGroup) != null) occurrence++;
}
return occurrence;
This is the code that i am using to search for the number of matches of a certain group. However there is no function like matcher.group(matcherGroup1, matcherGroup2) nor there is matcher.group(null) to search for multiple groups or all groups.
I have read Link groups (its stupid to group the arrays into one) or multiple groups?
Thanks
Can you not write your own matcherGroup implementation? The link you have provided is c#.
I have written a simple Java implementation which takes a single string, and then matches it against multiple RegExp patterns. The number of matches are then returned.
Alternatively please explain in more detail what you are trying to do.
package com.chocksaway;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
class SingleMatcher {
private Pattern pattern;
private java.util.regex.Matcher matcher;
private boolean found;
SingleMatcher(String input, String inputPattern) {
pattern = Pattern.compile(inputPattern);
matcher = pattern.matcher(input);
if (matcher.find()) {
this.found = true;
}
}
boolean getFound() {
return this.found;
}
}
class MatcherGroup {
private int matchedOccurances;
MatcherGroup(String input, List<String> multipleInputPattern) {
for (String inputPattern : multipleInputPattern) {
SingleMatcher eachSingleMatcher = new SingleMatcher(input, inputPattern);
if (eachSingleMatcher.getFound()) {
matchedOccurances++;
}
}
}
int getMatchedOccurances() {
return this.matchedOccurances;
}
}
/**
* Author milesd on 28/05/2017.
*/
public class RegExpMatcher {
public static void main(String[] args) {
SingleMatcher singleMatcher = new SingleMatcher("123", "\\d\\d\\d");
System.out.println(singleMatcher.getFound());
List<String> inputPatternList = new ArrayList<String>();
inputPatternList.add("\\d\\d\\d");
inputPatternList.add("John");
MatcherGroup matcherGroup = new MatcherGroup("John", inputPatternList);
System.out.println(matcherGroup.getMatchedOccurances());
}
}

Does it make sense to have input parameters to a class?

I created a class of DocumentFilter type as follows:
public class CustomDocumentFilter extends DocumentFilter
{
private StyledDocument styledDocument;
private JTextPane panetxt;
public CustomDocumentFilter(JTextPane panetxt) {
this.panetxt = panetxt; // Not really necessary
this.styledDocument = panetxt.getStyledDocument();
}
private final StyleContext styleContext = StyleContext.getDefaultStyleContext();
Pattern pattern = buildPattern(mystring);
private Pattern buildPattern(String mystring)
{
StringBuilder sb = new StringBuilder();
String[] toke = StringUtils.split(mystring,",");
for (String token : toke) {
sb.append("\\b");
sb.append(token);
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
Pattern p = Pattern.compile(sb.toString());
return p;
}
My question is: how to include mystring within the call of CustomDocumentFilter?:
//String mystring="lalala";
((AbstractDocument) editeur.getDocument()).setDocumentFilter(new CustomDocumentFilter(editeur));
EDIT:
Regarding the first way Jonathan suggests, I get this:
error: cannot find symbol Pattern pattern = buildPattern(mystring); ^ symbol: variable mystring location: class TextEditor.CustomDocumentFilter
I don't know if it has to do with the Pattern clause
Not 100% sure what is desired from the description. But I think your simply trying to ask how to get your local string value into your new CustomDocumentFilter object.
Well that is simple and you have choices! More than the two I show here.
first easy way is to add it to the constructor
public CustomDocumentFilter(JTextPane panetxt, String myString) {
...
pattern = buildPattern(mystring);
}
((AbstractDocument) editeur.getDocument()).setDocumentFilter(new CustomDocumentFilter(editeur, myString));
another way is to use a method that returns the object
public CustomDocumentFilter myFunction(String myString) {
pattern = buildPattern(mystring);
return this;
}
((AbstractDocument) editeur.getDocument()).setDocumentFilter(new CustomDocumentFilter(editeur).myFunction(myString));

Data validation with JOptionPane

I want to perform data validation while JOptionPane.I found the following approach but i am not really satisfied with it
import javax.swing.*;
import java.util.regex.*;
public class ValidateJOptionPane {
public static void main(String[] args) {
String input = JOptionPane.showInputDialog("Enter number: ");
Pattern p = Pattern.compile("[A-Z,a-z,&%$##!()*^]");
Matcher m = p.matcher(input);
if (m.find()) {
JOptionPane.showMessageDialog(null, "Please enter only numbers");
}
}
}
It would have been better and more sensible to use the regex to detect the characters that can be entered rather than testing for characters that can't be entered.
Is there a better and simpler way to do data validation with JOptionPane ? . I feel regex is overkill here.Correct me if i am wrong:P
P.S i am a beginner with Java
The long answer is, use DocumentFilter, see Implementing a Document Filter and DocumentFilter Examples for more details.
The problem with this is, you need to take control, you can't rely on the "simple", "helper" functionality provided by JOptionPane.showInputDialog, as you need access to the text field been used to prompt the user...
For example...
The following examples uses a (slightly) modified version of the PatternFilter from DocumentFilter Examples
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;
public class ValidateTest {
public static void main(String[] args) {
JTextField field = new JTextField(20);
Pattern p = Pattern.compile("[0-9]+");
((AbstractDocument) field.getDocument()).setDocumentFilter(new PatternFilter(p));
int option = ask("Enter number:", field);
if (option == JOptionPane.OK_OPTION) {
System.out.println("You have entered " + field.getText());
}
}
public static int ask(String label, JComponent comp) {
JPanel panel = new JPanel();
panel.add(new JLabel(label));
panel.add(comp);
return JOptionPane.showOptionDialog(null, panel, label,
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
}
public static class PatternFilter extends DocumentFilter {
// Useful for every kind of input validation !
// this is the insert pattern
// The pattern must contain all subpatterns so we can enter characters into a text component !
private Pattern pattern;
public PatternFilter(Pattern p) {
pattern = p;
}
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
String newStr = fb.getDocument().getText(0, fb.getDocument().getLength()) + string;
Matcher m = pattern.matcher(newStr);
if (m.matches()) {
super.insertString(fb, offset, string, attr);
} else {
}
}
public void replace(FilterBypass fb, int offset,
int length, String string, AttributeSet attr) throws
BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, string, attr);
}
}
}
Now, with a little clever design, you could write a simple helper class which built all this internally and provided a nice askFor(String label, Pattern p) style method that could return a String (or null if the user canceled the operation)
As you said "It would have been better and more sensible to use the regex to detect the characters that can be entered rather than testing for characters that can't be entered."
So you can just do the reverse checking then :
import javax.swing.*;
import java.util.regex.*;
public class ValidateJOptionPane {
public static void main(String[] args) {
String input = JOptionPane.showInputDialog("Enter number: ");
Pattern p = Pattern.compile("^[0-9]*$");
Matcher m = p.matcher(input);
if (!m.find()) { // if pattern doesn't match (not found)
JOptionPane.showMessageDialog(null, "Please enter only numbers");
}
}
}
[0-9] means digit 0-9 while * means some spaces

Java, make sure that a user doesn't enter numbers in a string

I'm trying to create a text based game in Java that I will ask for a user's name and insert it into the game. I'm trying to evaluate with the string that they entered has any number. i.e 09452 or asdf1234.
Here is the code that is relative to the problem.
String name, choiceSelection;
int choice;
name = JOptionPane.showInputDialog(null, "Enter your name!");
//CHECKS IF USER ENTERED LETTERS ONLY
if (Pattern.matches("[0-9]+", name))
{
throw new NumberFormatException();
}
else if (Pattern.matches("[a-zA-Z]+", name))
{
if (Pattern.matches("[0-9]+", name))
{
throw new NumberFormatException();
}
}
I'm trying to figure out if any number is in the string and if so, throw a NumberFormatException so that they know they didn't follow the correct prompt.
What is the best way to make sure the user doesn't enter numbers in the name String?
You can use a simpler check:
if (!name.replaceAll("[0-9]", "").equals(name)) {
// name contains digits
}
The replaceAll call removes all digits from the name. The equals check would succeed only when there are no digits to remove.
Note that throwing NumberFormatException in this case would be misleading, because the exception has a very different meaning.
Consider using a JFormattedTextField or input verifier to prevent the user from entering numbers in the first place. It may not be worth losing the JOptionPane simplicity for a throwaway project, but it simplifies things for the end user.
Or, You simply don't let the User to put any numeric value in textField .For that you are needed to create Customized PlainDocument say NonNumericDocument and setting the Document of JTextField object as that customized NonNumericDocument
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
class NonNumericDocument extends PlainDocument
{
#Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
{
if (str == null)
{
return;
}
char[] arr = str.toCharArray();
for (int i = 0; i < arr.length; i++)
{
if (Character.isDigit(arr[i]) || !Character.isLetter(arr[i]))//Checking for Numeric value or any special characters
{
return;
}
}
super.insertString(offs, new String(str), a);
}
}
//How to use NonNumericDocument
class TextFrame extends JFrame
{
JTextField tf ;
public void prepareAndShowGUI()
{
tf = new JTextField(30);
tf.setDocument(new NonNumericDocument());//Set Document here.
getContentPane().add(tf,BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater ( new Runnable()
{
#Override
public void run()
{
TextFrame tFrame = new TextFrame();
tFrame.prepareAndShowGUI();
}
});
}
}
You can use this NonNumericDocument with any JTextField in your code without worrying about handling of non-numeric characters explicitly.
If you want to allow the user to only enter letters you can do this:
if (name.matches("\\p{Alpha}+")) {
// name contains only letters
}
Another way to check it is using parseInt( String s ) method:
private boolean isNumber( String s ) {
try {
Integer.parseInt( s );
} catch ( Exception e ) {
return false; // if it is not a number it throws an exception
}
return true;
}

Categories