JOptionPane and Scanner input issue

2019-07-15 09:38发布

问题:

I'm writing a program where at one point, I need to print a String on a window using JOptionPane. The code for the line looks something like this:

JOptionPane.showMessageDialog(null, "Name: " + a.getName());

The getName function refers to the object a that i created that has a method that returns a String. However, when my code reaches this point, the program appears to enter some kind of infinite loop as the window never pops up and when using debug, it appears never-ending.

The main thing is, when I use getName, I am allowing the user the set this name with a different function earlier in the main driver.

getName() is basically one line, return name;

The code for my setName() function is basically:

Scanner a = new Scanner(System.in);
System.out.print("Pick a name: ");
name = in.nextLine();
a.close();

Name is a private variable in the class. The close() isn't necessary but I tried it to see if it had any effect.

What I did notice is that, if I use the above code, the window never pops up, and I get stuck in an infinite loop. However, if I simply change the name = line to anything, such as:

name = "foo";

The code runs smoothly, the window pops up, and I do not get stuck in a loop. Even if I do not input a name when the program prompts me to, resulting in a null String, the window still doesn't pop up. Can anyone help and advise me on why this is happening? Thanks.

回答1:

Using Scanner operations creates a block in the WaitDispatchSuport class used by JOptionPane which checks non-dispatch threads are free from blocking IO. Calling Scanner.close() will not un-block the thread.

One solution is to call showMessageDialog from the EDT :

Scanner a = new Scanner(System.in);
System.out.print("Pick a name: ");
final String name = a.nextLine();

SwingUtilities.invokeLater(new Runnable() {

   @Override
   public void run() {
      JOptionPane.showMessageDialog(null, "Name: " + name);             
   }
});


回答2:

This code snippet can help you

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        final String s = scanner.nextLine();
        SwingUtilities.invokeLater(() -> {
            JDialog dialog = new JDialog();
            dialog.setAlwaysOnTop(true);
            JOptionPane.showMessageDialog(dialog, s);
        });
}