stop user enters too many dots as input

i have a JTextfield where the user can enter in some input -> numbers 0-9 & decimal points, opeartors

how do i stop them from entering too many decimal points -> e.g if they have entered 1 already dont allow them enter another in that same input.
LVL 16
ellandrdAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
You can use a custom Document
sciuriwareCommented:
Add a key listener, that obtains the text so far,
deletes junk and puts the text back in the field.
;JOOP!
ellandrdAuthor Commented:
which means.....
Become a Microsoft Certified Solutions Expert

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

CEHJCommented:
See the following, but ensure zero or only one dot present
ellandrdAuthor Commented:
i have a key listener alraedy on the buttons, but my user can still enter in for example: 1234.0.0  where they should be only able to enter 1234.0 and the last .0 should be remove if they try typing it in...
CEHJCommented:
Something like

String text = null;
if ((text = getText(0, getLength())) != null && text.indexOf('.') < 0) {
      super.insertText(..................
}      
CEHJCommented:
A KeyListener doesn't prevent pastes
ellandrdAuthor Commented:
private void process( String input ) {
     
         if ( input.matches( "[\\d.]" ) && !operaterEntered ) {
            input1 += ( String ) input;
            dp.setText( dp.getText() + input );
       
 } else if ( input.matches( "[\\d.]" ) && operaterEntered ) {
            input2 += input;
            dp.setText( input2 );
       
       
        } else if ( input.indexOf( "." ) < 0 || input2.indexOf( "." ) < 0) {
            dp.setText( dp.getText() );

but this still alows me to enter in decimnal points after i have entered 1 in...
zzynxSr. Software engineerCommented:
ellandrd,
You really need to use a custom Document for your text fields.

Consider this one:
http://www.demo2s.com/Code/Java/Swing-JFC/Textfieldonlyacceptsnumbers.htm
zzynxSr. Software engineerCommented:
The important part is:

  class IntTextDocument extends PlainDocument {
    public void insertString(int offs, String str, AttributeSet a)
        throws BadLocationException {
      if (str == null)
        return;
      String oldString = getText(0, getLength());
      String newString = oldString.substring(0, offs) + str
          + oldString.substring(offs);
      try {
        Integer.parseInt(newString + "0");     // <<<<<< Here it checks that all that is currently entered (or even pasted) in the field/document
                                                                    // <<<<<< leads to a valid integer
        super.insertString(offs, str, a);
      } catch (NumberFormatException e) {
      }
    }
  }

In your case you nead a valid float, so for you

    Float.parseFloat(newString);

could work. (It will reject  "1234.0." in other words the 2nd '.' won't appear in the text field)
StillUnAwareCommented:
Hi ellandrd,

here is an example:

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;

public class InputLimiter extends JFrame {
  InputLimiter() {
    CustomizedTextField jtf = new CustomizedTextField(10);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    add(jtf);
    pack();
    setVisible(true);
  }
  public static void main(String[] args) {
    InputLimiter n = new InputLimiter();
  }
}

class CustomizedTextField extends JTextField {
     public CustomizedTextField(int cols) {
         super(cols);
     }
     public CustomizedTextField() {
         super();
     }
     protected Document createDefaultModel() {
         return new CustomizedDocument();
     }
     static class CustomizedDocument extends PlainDocument {
         public void insertString(int offs, String str, AttributeSet a)
             throws BadLocationException {
             if (str == null) {
                 return;
             }
             try {
                 Double.parseDouble(getText(0, getLength())+str);
                 super.insertString(offs, str, a);
             } catch(NumberFormatException nfe) {
                 return;
             }
         }
     }
 }
CEHJCommented:
You just need to use the example i posted together with the code i posted
zzynxSr. Software engineerCommented:
So try this:
everywhere where you currently have "JTextField" replace it by "FloatTextField":

class FloatTextField extends JTextField {
  public FloatTextField(float defval, int size) {
    super("" + defval, size);
  }

  protected Document createDefaultModel() {
    return new FloatTextDocument();
  }

  public boolean isValid() {
    try {
      Float.parseFloat(getText());
      return true;
    } catch (NumberFormatException e) {
      return false;
    }
  }

  public float getValue() {
    try {
      return Float.parseFloat(getText());
    } catch (NumberFormatException e) {
      return 0.0f;
    }
  }

  class FloatTextDocument extends PlainDocument {
    public void insertString(int offs, String str, AttributeSet a)
        throws BadLocationException {
        if (str == null)
           return;
        String oldString = getText(0, getLength());
        String newString = oldString.substring(0, offs) + str + oldString.substring(offs);
        try {
           Float.parseFloat(newString);
           super.insertString(offs, str, a);
      } catch (NumberFormatException e) {
      }
    }
  }

}
ellandrdAuthor Commented:
i dont want all these extra classes to limit the user from entering in a second decimal point - surely it is easier than this?
CEHJCommented:
>>surely it is easier than this?

No ;-)
CEHJCommented:
There's only *one* extra class
zzynxSr. Software engineerCommented:
>> i dont want all these extra classes
It's really the best way to do what you want.

>> There's only *one* extra class
Indeed. In my case the FloatTextField class.

Here's a demo program. Just compile and run it.

/*
 * FloatFieldTest.java
 *
 */

/**
 *
 * @author  zzynx
 */
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;

public class FloatFieldTest extends JFrame {
   
  public FloatFieldTest() {
    FloatTextField field = new FloatTextField();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    add(field);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
  }
 
  public static void main(String[] args) {
    FloatFieldTest n = new FloatFieldTest();
  }

 
    class FloatTextField extends JTextField {
      public FloatTextField() {
          super();
      }
       
      public FloatTextField(float defval, int size) {
        super("" + defval, size);
      }

      protected Document createDefaultModel() {
        return new FloatTextDocument();
      }

      public boolean isValid() {
        try {
          Float.parseFloat(getText());
          return true;
        } catch (NumberFormatException e) {
          return false;
        }
      }

      public float getValue() {
        try {
          return Float.parseFloat(getText());
        } catch (NumberFormatException e) {
          return 0.0f;
        }
      }

      class FloatTextDocument extends PlainDocument {
        public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException {
            if (str == null)
               return;
            String oldString = getText(0, getLength());
            String newString = oldString.substring(0, offs) + str + oldString.substring(offs);
            try {
               Float.parseFloat(newString);
               super.insertString(offs, str, a);
          } catch (NumberFormatException e) {
          }
        }
      }

    }
 
}
ellandrdAuthor Commented:
what to check input fro user and if there is a decimal point already entered dont allow another one?
zzynxSr. Software engineerCommented:
Without the extra class it would have looked as:

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;

public class FloatFieldTest extends JFrame {
   
  public FloatFieldTest() {
    JTextField field = new JTextField();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    add(field);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
  }
 
  public static void main(String[] args) {
    FloatFieldTest n = new FloatFieldTest();
  }
}

Now, only the FloatTextField class is added.
zzynxSr. Software engineerCommented:
>> what to check input fro user and if there is a decimal point already entered dont allow another one?
That's exactly what that code does (and more - of which you don't think of at this moment)
zzynxSr. Software engineerCommented:
>> if there is a decimal point already entered dont allow another one?
- And what about entering an A or a Z?
- And what if the user pastes a 2nd '.'?
- And what if ...

Al those situations are perfectly caught by that one class
ellandrdAuthor Commented:
but why did CEHJ (Date: 02/15/2006 10:20AM GMT) say "You just need to use the example i posted together with the code i posted"
zzynxSr. Software engineerCommented:
>> - And what if the user pastes a 2nd '.'?
So really "pastes" instead of "types". How are you going to 'catch' that with key listeners?
zzynxSr. Software engineerCommented:
>> but why did CEHJ
He'll probably tell you soon ;°)
ellandrdAuthor Commented:
zzzynx its my calculator - user can only enter numbers and decimals, but i only want them to be able to only enter 1 decimal in there input before clicking the operator!
zzynxSr. Software engineerCommented:
In the meantime you can also just try to replace each "JTextField" occurrence by "FloatTextField"
;°)
zzynxSr. Software engineerCommented:
>> zzynx its my calculator - user can only enter numbers and decimals
I know. Nevertheless I still recommend the approach mentioned above.
zzynxSr. Software engineerCommented:
Really. Why don't you just try it?
You can easily remove it again if it doesn't work.
CEHJCommented:
>>but why did CEHJ (Date: 02/15/2006 10:20AM GMT) say "You just need to use the example i posted together with the code i posted"

Because it satisfies the requirement you posted ;-)
ellandrdAuthor Commented:
>>Because it satisfies the requirement you posted ;-)

well it didnt as if it did i would nolonger be looking for help and i think it can be done without having to use all these extra classess too...

all i want to do it check if theres is 2 decimals? if yes, then remove last one entered.... surely its not that hard....
ellandrdAuthor Commented:
OK i came up with this:

 if ( input.matches( "[\\d.]" ) && !operaterEntered )
        {
            int i;
           
            for ( i = 0; i < input.length(); i++)
            {    
                if( ( input.charAt( i ) ) == '.' && i == input.length() )
                {  
                    input = input.replaceAll( ".", "" );
                    input1 += ( String ) input;
                }
            }
           
            input1 += input ;
            dp.setText( dp.getText() + input );
        }
zzynxSr. Software engineerCommented:
What about just setting a boolean to true when a '.' is detected.
Afterwards whenever a '.' is detected check if the boolean is already true. If it is: reject, otherwise: accept.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
zzynxSr. Software engineerCommented:
>> i think it can be done without having to use all these extra classess
1) It's only ONE extra class
2) I don't think it. I am sure it *can* be done. Question is: if that's the best way.
;°)
ellandrdAuthor Commented:
>>What about just setting a boolean to true when a '.' is detected.
>>Afterwards whenever a '.' is detected check if the boolean is already true. If it is: reject, otherwise: accept.

i have tried this, but i got it all mixed up...

i will code it up again and maybe you can have a look please?
zzynxSr. Software engineerCommented:
>> I will code it up again and maybe you can have a look please?
OK
ellandrdAuthor Commented:
here it is:


if ( input.matches( "[\\d.]" ) && !operaterEntered)
        {
            int i;
             
            if(dpAlreadyEntered)
            {
                for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.' && i == input.length() )
                    {  
                        input = input.replaceAll( ".", "" );
                        input1 += ( String ) input;
                    }
                }
            }
            else
            {
                for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.')
                    {  
                        dpAlreadyEntered = true;
                        break;
                    }
                }
               
                input1 += ( String ) input;
            }

            dp.setText( dp.getText() + input );
        }
zzynxSr. Software engineerCommented:
And what exactly doesn't work in that code?
ellandrdAuthor Commented:
when i run it - it dont stop me or remove the second decimal point if i enter one.  i get no errrors
zzynxSr. Software engineerCommented:
Why do you have the

        && i == input.length()

part in

>>  if( ( input.charAt( i ) ) == '.' && i == input.length() )

?
ellandrdAuthor Commented:
im checking each char to see if it is equal to "." and that it is the last charactor entered...

am i wrong?
zzynxSr. Software engineerCommented:
what is 'input'? Is it the NEW input?

So e.g.
When on the display you see  "123.0" and you press '.' again, then is input == "." ?
CEHJCommented:
>>
for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.')
                    {  
                        dpAlreadyEntered = true;
                        break;
                    }
                }
>>

can be replace by

dpAlreadyEntered = (input.indexOf('.') >-1);
ellandrdAuthor Commented:
here is the whole function:

private void process( String input ) {
          if ( input.matches( "[\\d.]" ) && !operaterEntered)
        {
            int i;
             
            if( dpAlreadyEntered )
            {
                for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.' && i == input.length() )
                    {  
                        input = input.replaceAll( ".", "" );
                    }
                }
            }
            else
            {
                for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.')
                    {  
                        dpAlreadyEntered = true;
                        break;
                    }
                }
            }
           
            input1 += ( String ) input;
            dp.setText( dp.getText() + input );
        }
        else if ( input.matches( "[\\d.]" ) && operaterEntered ) {
            input2 += input;
            dp.setText( input2 );
        } else if ( input.matches( "[*./+-]" ) ) {
            operator = input;
            operaterEntered = true;
        } else if ( input.matches( "=" ) ) {
            if ( "+".equals( operator ) )
                fResult = Float.parseFloat( input1 ) + Float.parseFloat( input2 );
            else if ( "-".equals( operator ) )
                fResult = Float.parseFloat( input1 ) - Float.parseFloat( input2 );
            else if ( "*".equals( operator ) )
                fResult = Float.parseFloat( input1 ) * Float.parseFloat( input2 );
            else if ( "/".equals(operator ) )
                fResult = Float.parseFloat( input1 ) / Float.parseFloat( input2 );
            else
                fResult = Float.parseFloat( input2 );
           
            input1 = Float.toString( fResult );
            input2 = "";
           
            dp.setText( Float.toString( fResult ) );
        }
    }
zzynxSr. Software engineerCommented:
>> am i wrong?
Yes, you are.
i can never be == input.length()
zzynxSr. Software engineerCommented:
since it's in a loop
>>  for ( i = 0; i < input.length(); i++)

remark the condition

         i < input.length()

So,
>> input = input.replaceAll( ".", "" );
is never executed
ellandrdAuthor Commented:
so how od i fix it?
zzynxSr. Software engineerCommented:
Replace it by just

     if ( dpAlreadyEntered )
          input = input.replaceAll( ".", "" );

ellandrdAuthor Commented:
the whole loop or just for(...) part?
zzynxSr. Software engineerCommented:
So,

            if( dpAlreadyEntered )
            {
                for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.' && i == input.length() )
                    {  
                        input = input.replaceAll( ".", "" );
                    }
                }
            }
            else
            {
                for ( i = 0; i < input.length(); i++)
                {    
                    if( ( input.charAt( i ) ) == '.')
                    {  
                        dpAlreadyEntered = true;
                        break;
                    }
                }
            }


becomes


  if ( dpAlreadyEntered )
       input = input.replaceAll( ".", "" );
  else
       dpAlreadyEntered = (input.indexOf('.') >-1);
ellandrdAuthor Commented:
yes i noticed it after i submitted - sorry...

ok if i enter a "." i cannot enter anything else after it... ;-(

should this happen?

if ( input.matches( "[\\d.]" ) && !operaterEntered)
        {
            if( dpAlreadyEntered )
                input = input.replaceAll( ".", "" );
            else
                dpAlreadyEntered = ( input.indexOf( '.' ) >-1 );
           
            input1 += ( String ) input;
            dp.setText( dp.getText() + input );
        }
zzynxSr. Software engineerCommented:
>> ok if i enter a "." i cannot enter anything else after it... ;-(
???
Code looks fine to me. Let's follow the flow:

You type a '9' e.g.

input = "9";

if ( input.matches( "[\\d.]" ) && !operaterEntered)  // digit or '.' (true)
        {
            if( dpAlreadyEntered )                                 // true
                input = input.replaceAll( ".", "" );             // it replaces '.' by "", so input stays "9"
            else
                dpAlreadyEntered = ( input.indexOf( '.' ) >-1 );
           
            input1 += ( String ) input;                // input1 becomes what it was + "9" appended
            dp.setText( dp.getText() + input );    // the display is set to what it was + "9" appended
        }
ellandrdAuthor Commented:
first time i satrt program i enter 9:

if ( input.matches( "[\\d.]" ) && !operaterEntered)  // digit or '.' (true)
        {
            if( dpAlreadyEntered )                                 // false as i have not entered a "." yet so skips next line.
                input = input.replaceAll( ".", "" );             // it replaces '.' by "", so input stays "9"
            else
                dpAlreadyEntered = ( input.indexOf( '.' ) >-1 );
           
            input1 += ( String ) input;                // input1 becomes what it was + "9" appended
            dp.setText( dp.getText() + input );    // the display is set to what it was + "9" appended
        }

next cahr i enter is "." so the flow is:

if ( input.matches( "[\\d.]" ) && !operaterEntered)  // digit or '.' (true)
        {
            if( dpAlreadyEntered )                                 // false again so skip next line
                input = input.replaceAll( ".", "" );             // it replaces '.' by "", so input stays "9"
            else
                dpAlreadyEntered = ( input.indexOf( '.' ) >-1 );  // now true as it picks up that i have entered a "."
           
            input1 += ( String ) input;                // input1 becomes what it was + "9." appended
            dp.setText( dp.getText() + input );    // the display is set to what it was + "9." appended
        }

after that i cant enter nothing in - not a digit or a decimal
zzynxSr. Software engineerCommented:
>> // input1 becomes what it was + "9." appended
You mean: input1 becomes what it was ("9") + "." appended  ==>  "9."

// the display is set to what it was + "9." appended
You mean: the display is set to what it was ("9") + "." appended  ==> "9."


Yeah, here's where an IDE debugger gets handy.
You'll have to find out where it goes wrong.
I don't see it. That's what I wanted to make clear with following the flow
zzynxSr. Software engineerCommented:
I see you posted a new question.
What about this one?
Mick BarryJava DeveloperCommented:
ellandrdAuthor Commented:
>>What about this one?

I havent forgot about it - dont worry!  Just still have not found out where i go wrong yet...
Mick BarryJava DeveloperCommented:
zzynxSr. Software engineerCommented:
>> Just still have not found out where i go wrong yet...
OK
ellandrdAuthor Commented:
ok i have been doing abit of looking around...

in my code:

input = input.replaceAll( ".", "" );  

i want to replace all "." points with "" using the above, but "." represent any charactor and therefore not allowing me to enter anthing after i press . on the keypad.

look here:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html#sum


so how do i just check for . instead of any charactors as this is what is causing problem...

im specifiing an "any charactor" by having:

replaceAll(".","") as replaceAll takes 2 string parameters... and a . represents any charactor as shown in documentation above...

so i need a workaround that will just look for . instead of any char....
sciuriwareCommented:
Escape the   .    by    \.


;JOOP!
zzynxSr. Software engineerCommented:
replaceAll("[.]","")
ellandrdAuthor Commented:
right but tell me what [] do or stand for - are they a "short hand" for something...
sciuriwareCommented:
Please read the JAVADOC one time.

;JOOP!
zzynxSr. Software engineerCommented:
or
    replaceAll("\\x2E","")

hex 2E being 46 decimal being the ascii code for '.'
CEHJCommented:
s = s.replaceAll("\\.","")
zzynxSr. Software engineerCommented:
>> Escape the   .    by    \.
won't work. You need two \'s.

So different possibilities are:

        replaceAll("\\.", "");
or
        replaceAll("[.]", "");
or
        replaceAll("\\x2E", "");
ellandrdAuthor Commented:
>>Please read the JAVADOC one time.

are you for real? or just  been smart...
sciuriwareCommented:
The regular expressions are some 50; must we read them all for you aloud?

;JOOP!
zzynxSr. Software engineerCommented:
ellandrd: read @ http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html

It's true that reading the docs would help you much further in finding simple things like that
ellandrdAuthor Commented:
zzynx & CEHJ  - thank you!  i will try these and get back to you in few mins...

ellandrd
zzynxSr. Software engineerCommented:
Do you believe I read them too before answering to you?
ellandrdAuthor Commented:
out of all these 3 ;

replaceAll("\\.", "");

replaceAll("[.]", "");

replaceAll("\\x2E", "");

this :

replaceAll("\\.", "");

worked!

thank you!

p.s splitting points as i got a telling off by objects last week for nothing doing so...
zzynxSr. Software engineerCommented:
All three work! I tried them myself:

System.out.println("1.2.3".replaceAll("\\.",""));
System.out.println("1.2.3".replaceAll("[.]",""));
System.out.println("1.2.3".replaceAll("\\x2E",""));
zzynxSr. Software engineerCommented:
>> p.s splitting points as i got a telling off by objects last week for nothing doing so...
Don't understand what you mean.
zzynxSr. Software engineerCommented:
btw,
Would you be so kind as to react on my question
@ http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_21737830.html ?
sciuriwareCommented:
Glad I've been to some help.

;JOOP!
ellandrdAuthor Commented:
>> p.s splitting points as i got a telling off by objects last week for nothing doing so...
>>Don't understand what you mean.

well to cut a long story short - last week when i accepted your comment(s) as my solution(s) and with objects & CEHJ making comments too, objects wasnt happy and basically i got a slap on the hand... ;-)
sciuriwareCommented:
Nobody is happy nowadays .....


;JOOP!
zzynxSr. Software engineerCommented:
Thanx 4 axxepting

>> well to cut a long story short ...
Well, experts expect to get the points they deserve.
Sounds logical but the reality isn't always like that.

>> Nobody is happy nowadays
I am. When I get what I deserve. ;°)
sciuriwareCommented:
I now you.
ellandrdAuthor Commented:
I cant always please everybody but my next question i'll try to be as fair as i can....
zzynxSr. Software engineerCommented:
>> I now you.
now you know ;°)
zzynxSr. Software engineerCommented:
>> my next question i'll try to be as fair as i can
Making mistakes is no problem.
As long as you correct them. ;°)

You can always ask to reopen a question:
(
post a zero-point question in http://www.experts-exchange.com/Community_Support/
Subject: Moderator Please Reopen
Body: Please reopen this question:
http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_xxxxxx.html
)
Once reopened you can close it again by applying the fair split.

In case of your previous Q I mentioned I would consider it.
ellandrdAuthor Commented:
>>In case of your previous Q I mentioned I would consider it

All you have to do is ask nicely...

This one is for you: "I would consider it" - and what if i didnt?
ellandrdAuthor Commented:
As requested: http://www.experts-exchange.com/Community_Support/Q_21740916.html

;-)  Everybody happy - as ive some work to get done - a website needs fixed!
zzynxSr. Software engineerCommented:
>> All you have to do is ask nicely...
I did in that Q but got no answer until now.

Thanks for considering it ;°)

>> This one is for you: "I would consider it" - and what if i didnt?
1) *If* an admin or PE agrees you have awarded in an *completely unfair* way,
     they *might* consider to reopen it and ask you for a fair reclose.
     They even *could* do the rewarding themselves.
     (Remark the many conditionals ;°)

2) experts may consider just skipping your future questions
CEHJCommented:
:-)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.