Stuck in loop with JOptionPane - java

I'm unsure of best practices with JOptionPanes, though this could equally just be a logic problem. I want an input box that asks for a name, checks it is a letter only string, and user can cancel.
I understand that cancelling a JOptionPane results in returning a null, which I've implemented at the start. The issue is that if a user enters incorrectly in the first pane, they cannot cancel from the second.
EDIT: worth pointing out that if user cancels I don't want to do anything with the name. This is the issue that forces me into the loop. Logic should be to check user input; if ==2 do nothing. If something else, validate is a word and use it. Loop around if not valid. The problem is the user can cancel later and the action of using the name is actioned anyway since it's in the second loop, with the value of 2.
I currently have:
JOptionPane optionPane1 = new JOptionPane(text, OK_OPTION, CANCEL_OPTION);
optionPane1.setWantsInput(true);
JDialog d1 = optionPane1.createDialog(null);
d1.setVisible(true);
name = optionPane1.getInputValue().toString();
if(name == null){
gamePaused = true;
}
else{
while(!name.matches("^[a-zA-Z]+$") || name.length() == 0){
JOptionPane optionPane2 = new JOptionPane("Please enter a word.\nTry again.", OK_OPTION, CANCEL_OPTION);
optionPane2.setWantsInput(true);
JDialog d2 = optionPane2.createDialog(null);
d2.setVisible(true);
name = optionPane2.getInputValue().toString();
}
///use name
}
Is there a better way of doing this, so that I can allow a user to cancel and escape the loop?

You can replace all your code with this one
do {
name = JOptionPane.showInputDialog(null, "Enter name here : ", "title", JOptionPane.OK_CANCEL_OPTION);
} while(name != null && !name.matches("^[a-zA-Z]+$"));
if (name == null) {
gamePaused = true;
} else {
//Do whatever want with the name
}

The problem is that inside your while loop, there is no further check whether the user pressed cancel (which means name == null). Once the user enters something invalid in his first attempt, he stays inside of the while loop and is asked for his name over and over again until there is a valid input, and the program does not care anymore about whether he clicked cancel. Therefore, you need to add before name = optionPane2.getInputValue().toString();:
if (optionPane2.getInputValue() == null) {
gamePaused = true;
break;
}

Inside your while loop, check if cancel is selected by user:
Add this inside the while loop:
if(optionPane2.getValue().toString().equals ("2")){ // 2 for close option in your case
break;
}

Related

JoptionPane closing without doing anything

Am working on a project where i need to ask the user to enter a path to save the program using jOptionPane but my problem is if the user dont put anything in the text and click cancel or ok am getting an error...i tried to control it buy checking the string if is Empty() or equals to null
Try to make a function for this JOptionPane, case you need back again, and don't forget to catch the errors with methods like NullPointerException.
public void optionPane(){
String m = JOptionPane.showInputDialog("your text...");
try{
if((m == null) || (m.equals(""))){
optionPane();
}
}catch(NullPointerException e){
optionPane();
}
}

How to fix only last line of array being checked for username and password when read from a file

I am reading usernames from a csv file in the format
admin1, apple, admin
staff1, orange, staff
with staff1 being on a new line and no matter how many lines I have, only the last line will be checked when login is occurring.
AtomicBoolean found = new AtomicBoolean(false);
btnLogin.setOnAction(e -> {
while (in.hasNextLine()) {
String s = in.nextLine().replaceAll("\\s+", "");
if (name.equals(sArray[0]) && password.equals(sArray[1])) {
lMessage.setText("correct");
openMainForm();
} else if (name.equals("") || password.equals("")) {
lMessage.setText("Please enter a username and password");
} else {
lMessage.setText("Please enter valid credentials");
}
}
});
I expect that if the username and password combination is found in the file they will be able to login and not just if the username and password is the last in the time
The problem is you are setting the action in a loop. That is, one action object being created for every pair and then being assigned. So, after last iteration, the action will be set to the latest object, which is obviously checking for last pair of username-password.
the loop translates to something like,
setOnAction(actionobject1 that checks for admin1, apple, admin)
setOnAction(actionobject2 that checks for staff1, orange, staff)
That effectively keeps last created object and check only for last pair
You might want to modify your logic so that there is only one action object. And then check for valid username-password pair.
Something like this:
btnLogin.setOnAction(e -> {
while (in.hasNextLine() ) {
// check condition here
// don't forget to break when successful
}
in.close();
});
Also, make sure you break the loop once successful pair is found. Otherwise the same thing will happen.

Handling of JOptionPane cancel button, which takes string as input

I want to take input as string from user through a Input dialog box, and also handle the situation if user presses cancel button.
Any suggestions?
You may use the showInputDialog method of class JOptionPane .
If the user hits Cancel, the returned value is null.
Also note, as #mKorbel said in the comments, that you will also get null if the windows has been closed directly.
String result = JOptionPane.showInputDialog("Please enter something");
if(result == null){
System.out.println("User pressed CANCEL, or window has been closed");
}
else{
// do something with the String
}
Try this:
if(result == null){
System.out.println("User pressed CANCEL, or window has been closed");
System.exit(0);
}

Java do-while with multiple string validation

Trying to create a simple program that has three options for text input. If the user types one of the three, the program moves on. If the user types something else, the program loops back and asks for the input again until a proper response is given.
Using a drop down list or other method will not work, as this is for an assignment.
System.out.print("Enter one of the following: cheese, water, or burger: ");
userMedium = user_input.nextLine( ); // store user input as a string
mediumConvert = userMedium.toLowerCase();
boolean verifyName;
if (mediumConvert.equals("cheese") || mediumConvert.equals("water") || mediumConvert.equals("burger")){
verifyName = false;
} else {
verifyName = true;
}
while (verifyName = true){
System.out.println("Please input a valid medium (cheese, water, or burger): ");
userMedium = user_input.nextLine( );
mediumConvert = userMedium.toLowerCase();
}
This is what I have set up so far, but this just keeps repeating the loop OVER AND OVER. After this section I want to execute a switch to work off each of the three correct responses.
I've spent the last hour on google and YouTube, but everything I found is using integers. It seems pretty easy to validate user input when it is just a number and an operand. But how do I use three possible strings?!
while (verifyName = true)
↑
You're assigning and not comparing. The expression of the assignment returns the assigned value, so your loop is equivalent to:
while (true)
You should change it to:
while (verifyName)
Basically, you should write while (verifyName == true), but it's redundant since it's like asking "Is it true that verifyName has the value true?". Also it prevents potential bugs, like just inserting one = instead of two..
Noticed two things:
1.) By doing
while(verify = true)
you are actually assigning the value true to verifyName. You need to use
while(verifyName)
2.) Where do you reassign the value of verifyName?
You should be validating and reassigning inside the while block.
Also you should consider cleaner alternative solution, but that can wait for another day.
You will never break out of the whileloop because the variable verifyName is never updated inside the loop. This means that you'll either never execute the loop because the user inserted the input you wanted or you'll end up with an infinite loop.
You need to do your input verification inside the loop as well and be careful with the boolean validation as well.
Something like:
while (verifyName) {
System.out.println("Please input a valid medium (air, water, or steel): ");
userMedium = user_input.nextLine( );
mediumConvert = userMedium.toLowerCase();
if (mediumConvert.equals("cheese") || mediumConvert.equals("water") || mediumConvert.equals("burger")){
verifyName = false;
} else {
verifyName = true;
}
}

input validation and refuse improper input

I am attempting to validate user input. I have tried some if statements and attempted Boolean. I cant get anything to give the output or rather the validation I am wanting
Users are asked to choose between "red" or "blue" I want them to be required to type either "red" or "blue". I know this could be solved easier through buttons but I am trying to use string input. the code below give an example of where i am.
custColorMsg = "Which color do you want your shirt to be red or blue?";
customerColor = getstringInput(custColorMsg);
String color = null
if( customerColor.equalsIgnoreCase("yes")) {
color = true}
if( customerColor.equalsIgnoreCase("no")) {
color = true}
else if(!customerColor.equalsIgnoreCase("yes" || "no") {
color = false}
I know this last portion is wrong I am just unsure how to go about fixing it. Customers will have three chances to input a valid response then the program will terminate, this portion i can handle. If i can just figure out how to accept "yes" or "no" and refuse anything else.
In terms of the design of this program, I would recommend adding a for loop, that goes from 0 to 2 (this will iterate 3 times). Within the loop, the program can determine what the user's input is. I would also recommend looking at my syntax for the for loop below, I use ifs, else ifs and elses to evaluate the data set more efficiently.
The implementation of the program could be:
for(int i = 0; i < 3; i++)
{
customerColor = getstringInput(custColorMsg);
String color = null
if( customerColor.equalsIgnoreCase("yes")) {
color = true;
break;
}
else if( customerColor.equalsIgnoreCase("no")) {
color = true;
break;
}
else{
color = false;
}
custColorMsg = "Invalid Input, Please Input Again";
}
This will give the user 3 times to input the data, and if they input it correctly, it will stop asking, however, if they do not, it will ask again until they run out of attempts.
There's a few things wrong with your approach.
The semantics of your variable names are a bit off. Which makes the code difficult to read. For example, the variable color which you have defined here as a String, but consistently use as a Boolean is a bit confusing. I'm guessing you mean to define it as a Boolean type and intend to use it as the breaking condition from your loop - it would be more meaningful to name the it as isValidColor or something along those lines.
The following line doesn't do what you think it does:
customerColor.equalsIgnoreCase("yes" || "no")
The method equalsIgnoreCase() takes in a String and not a Boolean like this line of your code will have for an argument. Since the || will resolve to a Boolean value of true or false. Furthermore, those are bad operand types for that operator and the code won't compile.
For your control structure you can use a while loop which will exit when you have reached the max amount of tries or entered a valid response.
Here's a working Console version of what you are trying to accomplish:
String custColorMsg = "Which color do you want your shirt to be red or blue?";
String customerColor;
Boolean validInput = false;
Scanner in = new Scanner(System.in);
int tries = 0;
while (tries < 3 && !validInput)
{
System.out.println(custColorMsg);
customerColor = in.nextLine();
if( customerColor.equalsIgnoreCase("red")) {
validInput = true;
}
else if( customerColor.equalsIgnoreCase("blue")) {
validInput = true;
}
tries++;
}

Categories