1

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?

Luke
  • 367
  • 1
  • 3
  • 10
  • 1
    name can't possibly be null, because it's obtained by calling `optionPane1.getInputValue().toString();`, and `toString()` will never return null. Your JOptionPanel constructor call is also wrong. Read its javadoc: https://docs.oracle.com/javase/8/docs/api/javax/swing/JOptionPane.html#JOptionPane-java.lang.Object-int-int-. The second argument can't be OK_OPTION. In general, you should use the static showXxx methods of JOptionPane to show one. – JB Nizet Nov 30 '19 at 13:13
  • If your `getInputValue()` returns `null`, your code will crash since you call `toString()` on it, resulting in a situation like `null.toString()` which yields a `NPE`. – Zabuzard Nov 30 '19 at 13:32
  • Possibly, check this [answer](https://stackoverflow.com/questions/13055107/joptionpane-check-user-input-and-prevent-from-closing-until-conditions-are-met) ,for better approach. – Dhyey Shah Nov 30 '19 at 14:23

3 Answers3

1

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
}
b.GHILAS
  • 2,273
  • 1
  • 8
  • 16
0

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;
}
  • optionPane2 doesnt return null however. It will return "uninitializedValue" . this condition has no meaning here. – Dhyey Shah Nov 30 '19 at 14:30
  • This doesn't break me out of the while loop though, it only breaks out of the if statement. – Luke Nov 30 '19 at 14:58
  • @Luke break is for coming out of loops,not if conditions. "It only breaks out of the is statement" makes no sense. – Dhyey Shah Nov 30 '19 at 16:58
  • True, but break is a sign of bad logic often. And in this specific case does nothing helpful. I appreciate your advice though. – Luke Nov 30 '19 at 22:26
-1

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;
}
Dhyey Shah
  • 582
  • 7
  • 23
  • This also doesn't break me out of the inner loop. And even if it could, it would attempt to use the value of name, 2, to action with. I need it not to attempt to action unless the name is a string. – Luke Nov 30 '19 at 15:00
  • @Luke String name need not be "2",getValue() returns value for selected option i.e. "1" for pressing Ok and "2" for pressing Cancel. I am just comparing it, to know which button is pressed. – Dhyey Shah Nov 30 '19 at 17:03