JTextField limiting input after period - java

I'm writing a CashRegister program and I'm currently working on the CashierView where I have added an option for the Cashier to input the amount of cash received by the customer. I now formatted it so that the user only can input numbers and 1 period. I now want to limit the numbers you can input after the period to two. I'm struggling to make this work.
I commented out one of the codes that I tried, but didn't work, incase it might be interesting.
Appreciate all the help!
Br,
Victor
private void jCashReceivedKeyTyped(java.awt.event.KeyEvent evt) {
char c = evt.getKeyChar(); //Allows input of only Numbers and periods in the textfield
//boolean tail = false;
if ((Character.isDigit(c) || (c == KeyEvent.VK_BACKSPACE) || c == KeyEvent.VK_PERIOD)) {
int period = 0;
if (c == KeyEvent.VK_PERIOD) { //Allows only one period to be added to the textfield
//tail = false;
String s = getTextFieldCash();
int dot = s.indexOf(".");
period = dot;
if (dot != -1) {
evt.consume();
}
}
//. if (tail=true){ //This is the code that I tried to use to limit input after the period to two
// String x = getTextFieldCashTail();
// if (x.length()>1){
// evt.consume();
// }
// }
}
else {
evt.consume();
}
}

If you're dead set on doing this with a KeyEvent, here's one possible method:
private void jCashReceivedKeyTyped(java.awt.event.KeyEvent evt) {
char c = evt.getKeyChar(); //Allows input of only Numbers and periods in the textfield
if ((Character.isDigit(c) || (c == KeyEvent.VK_BACK_SPACE) || c == KeyEvent.VK_PERIOD)) {
String s = getTextFieldCash();
int dot = s.indexOf(".");
if(dot != -1 && c == KeyEvent.VK_PERIOD) {
evt.consume();
} else if(dot != -1 && c != KeyEvent.VK_BACK_SPACE){
String afterDecimal = s.substring(dot + 1);
if (afterDecimal.length() > 2) {
evt.consume();
}
}
}
}
Hope this helps. Just keep in mind that by listening to a KeyEvent, if someone copies and pastes values into your JTextField, this won't catch that. If you want to catch any possible type of input, you'll want to use a DocumentListener. If you're wondering how to use a DocumentListener, here is some code that shows how to use it on a JTextField.

Related

Is it okey to use evt.consume() in this case?

So I have a textfield which I want to be max length 10 and only letters, this is what I've came up with:
private void textField1KeyTyped(java.awt.event.KeyEvent evt) {
char c= evt.getKeyChar();
if( !(Character.isAlphabetic(c)) ){
evt.consume();
}
if ((textField1.getText().length()) > 10){
evt.consume();
}
}
It kind of works but I've seen some tutorials that use something like this:
private void textField1KeyTyped(java.awt.event.KeyEvent evt) {
char c= evt.getKeyChar();
if( (Character.isAlphabetic(c)) ){
if((textField1.getText().length()) <= 10){
textField1.setEditable(true);
}else {
textField1.setEditable(false);
}
}else {
if( (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE) ){
textField1.setEditable(true);
}else {
textField1.setEditable(false);
}
}
}
Which one is right?
Both will stop the text-field from consuming further keys.
calling InputEvent.consume() marks the event as consumed, so that the textfield will not consume it and add the key to it's contents.
See What does e.consume() do in java
disabling editing on the textfield with setEditable(false) will also prevent the textfield from editing, that is consuming the key. But it also makes this behaviour, the lock, visible to the user.

Make an algorithm start again?

So I'm pretty new to coding with Java (started yesterday). What I am trying to do is to make an Input of an Integer, if the int c it is higher than 1 or lower than 0 (if it is not 1 or 0), I want it to start again. If int c equals either 1 or 0, I want the alogrithm to continue. I tried to insert some kind of loops after if(c > 1 || c < 0) but it does not seem to work and only spams my console with the result. Is there any easy way to make the algorithm start over again? I'm already trying to fix this for more than 2 hours, but I'm just confusing me over and over again.
// more code up here but it is unimportant
int c = sc.nextInt();
if(c > 1 || c < 0) {
result = result + wrong;
System.out.println(result);
} else if (c == 1) {
result = result + notImplemented;
System.out.println(result);
} else if (c == 0) { //more code follows here but is unimportant
So you want to ask for input again, i assume.
A simple way could be:
int c = sc.nextInt();
while (c > 1 || c < 0) {
c = sc.nextInt();
}
//code continues
You can use while in this case and use break to exit:
while (scanner.hasNext()) {
int c = sc.nextInt();
if(c > 1 || c < 0) {
result = result + wrong;
System.out.println(result);
} else if (c == 1) {
result = result + notImplemented;
System.out.println(result);
break;
} else if (c == 0) {
...
break;
}
}
scanner.close();
You need to use a loop so you have
while(true){
int c = sc.nextInt();
if(c > 1 || c < 0) {
result = result + wrong;
System.out.println(result);
break;
} else if (c == 1) {
result = result + notImplemented;
System.out.println(result);
} else if (c == 0) { //more code follows here but is unimportant
...
}
Since you say you are new, I'll do a little explanation:
A While loop repeats what is in it's code block (i.e within the { }) for as long as a certain condition is true. In the case of my answer I did while(true) meaning it will keep repeating until something causes it to stop. In this case I used a break which forces the loop to end/stop.
Use hasNextInt() and a while loop to iterate over the data:
while (sc.hasNextInt()) {
int aInt = sc.nextInt();
//logic here
}
Documentation for hasNextInt() method:
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextInt()
You can put your code in a function (which I hope is already the case) and then when you don't have the expected result and want to call it again, just do so by calling your function inside itself.
It's called recursion.
You can learn more here .
For example :
// more code up here but it is unimportant
public void myFunction(){
int c = sc.nextInt();
if(c > 1 || c < 0) {
result = result + wrong;
System.out.println(result);
} else if (c == 1) {
result = result + notImplemented;
System.out.println(result);
} else if (c == 0) { //more code follows here but is unimportant
}
//You want to call your function again
myFunction();
}

Trying to understand a method

I have a method which I have to write called personalize. This is what it's suppose to do / what I've done so far.
// personalize takes a String and validates it
// if it is a valid plate, it changes the plateNumber to
// the new plateNumber and calculates the cost of the plate.
// the method returns true if the new plateNumber is valid and the plate was changed,
// and false if the new plateNumber was invalid and no changes were made.
// A personalized plate may be 3 up to 7 chars and 1 space or dash
// Use letters, numbers, dashes, and spaces ONLY
// A personalized plate costs $10 extra plus $5 per letter (not including dashes or spaces)
public boolean personalize(String vanity)
{
boolean valid = true;
vanity = "";
for(int i = 0; i < vanity.length(); i++)
{
if(vanity.length() < 7 && vanity.length() > 3)
{
valid = true;
}
if(Character.isLowerCase(vanity.charAt(i)) || vanity.length() > 7 || vanity.length() < 3 ||
vanity.charAt(i) == '!' || vanity.charAt(i) == '.' || vanity.charAt(i) == '$' ||
vanity.charAt(i) == '#' || vanity.charAt(i) == '*' || vanity.charAt(i) == '_' ||
vanity.charAt(i) == '#' || vanity.charAt(i) == '^' || vanity.charAt(i) == '&')
{
valid = false;
}
}
if(valid = true)
{
plateCost += 25;
}
return valid;
}
I know everything I have in this method isn't completely correct but I'm extremely confused on it. I was thinking about writing a helper method, but I'm unsure if it would be for the cost (newCost) or for the new plate number (personalizedPlate). Or would I have to write both? I'm not simply looking for the answer to my work. I'm really looking for someone to help me through the problem to better understand what to do and why I have to do it that way.
Don't try to do everything in one method. The following code demonstrates one way of implementing these requirements:
public class Plate {
int plateCost = 0;
public boolean personalize(String vanity) {
boolean valid = validate3to7chars(vanity);
valid = valid && hasOnlyOneSpaceOrDash(vanity);
valid = valid && hasValidCharacters(vanity);
if (valid) {
String plateWithoutSpacesAndDashes = vanity.replaceAll(" ", "").replaceAll("-", "");
plateCost = 10 + plateWithoutSpacesAndDashes.length() * 5;
}
return valid;
}
private boolean hasValidCharacters(String vanity) {
String toVerify = vanity.replaceAll(" ", "").replaceAll("-", ""); //remove dashes and spaces
return toVerify.matches("[0-9a-zA-Z]+"); // verify that the place has only numbers and letters
}
private boolean hasOnlyOneSpaceOrDash(String vanity) {
boolean spaces = vanity.lastIndexOf(" ") == vanity.indexOf(" ");
boolean dashes = vanity.lastIndexOf("-") == vanity.indexOf("-");
return spaces && dashes;
}
private boolean validate3to7chars(String vanity) {
return vanity.length() >= 3 && vanity.length() <= 7;
}
public static void main(String[] args) {
Plate p = new Plate();
System.out.println(p.personalize("abc-52s")); // true
System.out.println(p.personalize("123 52s")); // true
System.out.println(p.personalize(" abc62s")); // true
System.out.println(p.personalize("abc56s ")); // true
System.out.println(p.personalize("abc562+")); // false
System.out.println(p.personalize("12345678")); // false
}
}

Cannot find symbol, Java and Strings

I've tried tinkering around with this for awhile and have yet to figure out what its giving me this error. The code is far from complete but I'm just trying to figure out why it says it can't find variable ch1. Any help is greatly appreciated!
public class PhoneNumber {
String phoneNumber;
public PhoneNumber(String num) {
phoneNumber = num;
}
public String decodePhoneNumber() {
// Takes string form phone number and decodes based on number pad
// Find code that makes if statement not care about caps
// so if a || b || c number[cnt] = 1 etc..
for (int cnt = 0; cnt < phoneNumber.length(); cnt++) {
char ch1 = phoneNumber.charAt(cnt);
if (Character.ch1.equalsIgnoreCase("a") || ("b") || ("c")) {
} else if (ch1.equalsIgnoreCase("d" || "e" || "f")) {
} else if (ch1.equalsIgnoreCase("j" || "k" || "l")) {
} else if (ch1.equalsIgnoreCase("m" || "n" || "o")) {
} else if (ch1.equalsIgnoreCase("p" || "q" || "r" || "s")) {
} else if (ch1.equalsIgnoreCase("t" || "u" || "v")) {
} else {
}
}
}
}
You have syntax errors and that is why you cannot find ch1.
Try modifying your code as per this syntax. These changes need to be done in all the conditionals.
if ((ch1 == 'a') || (ch1 == 'b') || (ch1 =='c')) {
If you want to make it work regardless of capital letters then you would need to normalize the input to lower case and then do the character comparison:
char ch1 = phoneNumber.toLowerCase().charAt(cnt);
if (ch1 == 'a' || ch1 == 'b' || ch1 == 'c') {
// Do something
}
...

Accept only numbers and a dot in Java TextField

I've got one textField where I only accept numbers from the keyboard, but now I have to change it as it's a "price textField" and I would also need to accept a dot "." for any kind of prices.
How can I change this in order to get what I need?
ptoMinimoField = new JTextField();
ptoMinimoField.setBounds(348, 177, 167, 20);
contentPanel.add(ptoMinimoField);
ptoMinimoField.setColumns(10);
ptoMinimoField.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char caracter = e.getKeyChar();
if (((caracter < '0') || (caracter > '9'))
&& (caracter != '\b')) {
e.consume();
}
}
});
As suggested by Oracle ,Use Formatted Text Fields
Formatted text fields provide a way for developers to specify the valid set of characters that can be typed in a text field.
amountFormat = NumberFormat.getNumberInstance();
...
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);
I just use a try-catch block:
try {// if is number
Integer.parseInt(String);
} catch (NumberFormatException e) {
// else then do blah
}
JTextField txField = new DoubleJTextField();
Create a file DoubleJTextField.java and be happy
public class DoubleJTextField extends JTextField {
public DoubleJTextField(){
addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char ch = e.getKeyChar();
if (!isNumber(ch) && !isValidSignal(ch) && !validatePoint(ch) && ch != '\b') {
e.consume();
}
}
});
}
private boolean isNumber(char ch){
return ch >= '0' && ch <= '9';
}
private boolean isValidSignal(char ch){
if( (getText() == null || "".equals(getText().trim()) ) && ch == '-'){
return true;
}
return false;
}
private boolean validatePoint(char ch){
if(ch != '.'){
return false;
}
if(getText() == null || "".equals(getText().trim())){
setText("0.");
return false;
}else if("-".equals(getText())){
setText("-0.");
}
return true;
}
}
Don't ever use a KeyListener for this. Your code above has two serious bugs, both caused by the use of a KeyListener. First, it will miss any text that gets pasted in. Whenever I find a field that filters out non-digits, I always try to paste in some text, just for fun. Nine times out of ten, the text gets accepted, because they used a key listener.
Second, you didn't filter out modifiers. If the user tries to save their work by typing control-s while they're in this field, your key listener will consume the event. And if your application assigns, say, a control-5 or alt-5 shortcut to some action, this KeyListener will add a 5 to the field when they type it, even though the user wasn't trying to type a character. You did figure out that you needed to pass the backspace key, but that's not all you need to pass. Your arrow keys won't work. Neither will your function keys. You can fix all these problems, but it starts to be a lot of work.
There's a third disadvantage, but it only shows up if you adapt your application to a foreign alphabet, particularly one that takes multiple keystrokes to generate a single character, like Chinese. These alphabets make KeyListeners useless.
The trouble is this. You need to filter characters, but KeyListeners aren't about characters, they're about keystrokes, which are not the same thing: Not all keystrokes generate characters, and not all characters are generated by keystrokes. You need an approach that looks at characters after they've been generated, and after modified keystrokes have already been filtered out.
The simplest approach is to use a JFormattedTextField, but I've never liked that approach, because it doesn't format or filter as you type. So instead, I will use a DocumentFilter. DocumentFilters don't operate on keystrokes, they operate on the text strings as they get inserted to your JTextField's data model. Hence, all the control-keys, arrow and function keys and such don't even reach the DocumentFilter. All pasted text goes through the DocumentFilter, too. And, for languages that take three keystrokes to generate a single character, the DocumentFilter doesn't get invoked until the character is generated. Here's what it looks like:
ptoMinimoField = new JTextField();
ptoMinimoField.setBounds(348, 177, 167, 20); // Don't do this! See below.
contentPanel.add(ptoMinimoField);
ptoMinimoField.setColumns(10);
PlainDocument document = (PlainDocument) ptoMinimoField.getDocument();
document.setDocumentFilter(new DigitFilter());
}
The DigitFilter class looks like this:
public class DigitFilter extends DocumentFilter {
#Override
public void insertString(FilterBypass fb, int offset, String text,
AttributeSet attr) throws BadLocationException {
super.insertString(fb, offset, revise(text), attr);
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
super.replace(fb, offset, length, revise(text), attrs);
}
private String revise(String text) {
StringBuilder builder = new StringBuilder(text);
int index = 0;
while (index < builder.length()) {
if (accept(builder.charAt(index))) {
index++;
} else {
// Don't increment index here, or you'll skip the next character!
builder.deleteCharAt(index);
}
}
return builder.toString();
}
/**
* Determine if the character should remain in the String. You may
* override this to get any matching criteria you want.
* #param c The character in question
* #return true if it's valid, false if it should be removed.
*/
public boolean accept(final char c) {
return Character.isDigit(c) || c == '.';
}
}
You could write this as an inner class, but I created a separate class so you can override the accept() method to use any criteria you want. You may also notice that I don't test for digits by writing this:
(c < '0') || (c > '9')
Instead, I do this:
Character.isDigit()
This is faster, cleaner, and works with foreign numbering systems. I also don't need your test for the backspace character, '\b'. I'm guessing that your first KeyListener was filtering out the backspace key, which was your first clue that it was the wrong approach.
And on an unrelated note, don't hard code your component positions. Learn how to use the LayoutManagers. They're easy to use, and they'll make your code much easier to maintain.
Have you looked at a JFormattedTextField? It would seem it does what you want.
Enter the double number of JTextField in java
private boolean dot = false;
private void txtMarkKeyTyped(java.awt.event.KeyEvent evt) {
char vChar = evt.getKeyChar();
if (txtMark.getText().equals(""))
dot = false;
if (dot == false){
if (vChar == '.') dot = true;
else if (!(Character.isDigit(vChar)
|| (vChar == KeyEvent.VK_BACK_SPACE)
|| (vChar == KeyEvent.VK_DELETE))) {
evt.consume();
}
} else {
if (!(Character.isDigit(vChar)
|| (vChar == KeyEvent.VK_BACK_SPACE)
|| (vChar == KeyEvent.VK_DELETE))) {
evt.consume();
}
}
}
This bit of code;
if (((caracter < '0') || (caracter > '9'))
&& (caracter != '\b')) {
decides whether to consume the key event. You need to update the condition so it doesn't consume the dot character.
Just right click on TextField / events / key / keytyped
if(!Character.isDigit(evt.getKeyChar())){
evt.consume();}
/////////////
JTextField ptoMinimoField = new JTextField();
ptoMinimoField.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
boolean ret = true;
try {
Double.parseDouble(ptoMinimoField.getText()+e.getKeyChar());
}catch (NumberFormatException ee) {
ret = false;
}
if (!ret) {
e.consume();
}
}
});
maybe can help you for filtering keytyped just number and dot
public void filterHanyaAngkaDot(java.awt.event.KeyEvent evt){
char c = evt.getKeyChar();
if (! ((Character.isDigit(c) ||
(c == KeyEvent.VK_BACK_SPACE) ||
(c == KeyEvent.VK_DELETE))
)&& c==KeyEvent.VK_COMMA
)
{
evt.consume();
}
}
JTextField txtMyTextField = new JTextField();
numOnly(txtMyTextField);
public void numOnly(Object objSource){
((Component) objSource).addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
String filterStr = "0123456789.";
char c = (char)e.getKeyChar();
if(filterStr.indexOf(c)<0){
e.consume();
}
}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {}
});
}
WARNING: This function does not follow proper java documentation
guide.
I have been using this solution, it's simple and efficient:
jtextfield.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char vChar = e.getKeyChar();
if (!(Character.isDigit(vChar)
|| (vChar == KeyEvent.VK_BACK_SPACE)
|| (vChar == KeyEvent.VK_DELETE))) {
e.consume();
}
}
});
private boolean point = false;
private void txtProductCostPriceAddKeyTyped(java.awt.event.KeyEvent evt)
{
char Char = evt.getKeyChar();
if (txtProductCostPriceAdd.getText().equals(""))
point = false;
if (point == false){
if (Char == '.') point = true;
else if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
evt.consume();
}
} else {
if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
evt.consume();
}
}
}
JTextField textField = new JTextField();
textField.setColumns(10);
textField.addKeyListener(new KeyAdapter() {
#Override
public void KeyTyped(KeyEvent e) {
if (!(e.getKeyChar() >= '0' && e.getKeyChar() <= '9')) {
e.consume();
}
}
})
this is the easiest method i have found so far, and it works without any error

Categories

Resources