Search code examples
javaswingjoptionpanesizing

How do I change the size and location of JOptionPane.showOptionDialog()


Okay, so here's the deal. Currently, I am using this:

 String[] choices = {"Rock", "Paper", "Scissors"};
 String input = (String) JOptionPane.showInputDialog(null, "Please, make your choice", "Rock Paper Scissors!", JOptionPane.QUESTION_MESSAGE, null, choices, choices[0]); 

Which is what I need. It creates a drop down menu that allows the user to select Rock, Paper, or Scissors and then outputs it into a String. The problem is, the window that it pops in is REALLY small, and is in the center of the screen. I want to re-size it to be 970 pixels by 300 pixels, and to appear at the location of 950 pixels and 0 pixels.

Now, before you say it, I HAVE tried to use JFrames for this, because I know how to get it the size and at the location I want it. However, I can't get the ActionListener to behave in the way that I want it to.

public static void main(String args[]) throws IOException
{
    JFrame hi = new JFrame("Hi");
    hi.setSize(970, 300);
    hi.setLocation(950, 0);
    System.out.println("Hi");
    Picture Hi = new Picture("c:/The Game/Cool.png");
    Hi.display();

    JButton B = new JButton("Hey There!");
    hi.add(B);

    int c = Output(hi);
}
public int Output(JFrame b)
{
    int j = 0;
    j = //CODE NEEDED HERE
    return j;
}
@Override
public void actionPerformed(ActionEvent arg0) {


}

So, the problem with this is that I need the JFrame to pop up in then "CODE NEEDED HERE" section, and then, upon clicking the button, to return a certain value, and then to close out of the JFrame. However, the JFrame doesn't wait for the Output() function, and it immediately returns j, which is equal to 0. Instead, it just does whatever is in the actionPerformed function.

So, I am asking for a solution to either one of these problems. How to either re-size the JOptionPane.showInputDialog() or to get the JFrame to return an int value upon clicking a button.

Sorry if this is really poorly explained, I'm really new to JOptionPane and JFrames.


Solution

  • JOptionPane is quite configurable, it's also nicely self contained, taking a lot of the repetitive, boil plate code and hiding it away in an easy to use package.

    But that doesn't mean you have to use it that way, you can simply create an instance of JOptionPane, which is just an ancestor of JComponent and add it to what ever you want.

    The difficulty is plumbing all the functionality back together, so you can respond to the buttons, for example.

    Just beware, your example places the dialog under my task bar (yes, mine is at the top of the screen), so I can tell you, as a user, that will annoy me!

    Big Dialog

    So, this example basically wraps up all the boiler plate code into a simple class/method, which makes it easy to repeatedly prompt the user the same question, over and over again...

    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import javax.swing.JDialog;
    import javax.swing.JOptionPane;
    import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
    import static javax.swing.JOptionPane.UNINITIALIZED_VALUE;
    import static javax.swing.JOptionPane.VALUE_PROPERTY;
    import javax.swing.border.EmptyBorder;
    
    public class Test {
    
        public static void main(String[] args) {
            String pick = Picker.pick();
            System.out.println("You picked " + pick);
            System.exit(0);
        }
    
        public static class Picker {
    
            public static String pick() {
                String[] choices = {"Rock", "Paper", "Scissors"};
    
                JOptionPane pane = new JOptionPane("Please, make your choice", JOptionPane.QUESTION_MESSAGE,
                        OK_CANCEL_OPTION, null, null, null);
                pane.setWantsInput(true);
                pane.setSelectionValues(choices);
                pane.setInitialSelectionValue(choices[0]);
    
                JDialog dialog = new JDialog();
                dialog.setModal(true);
    
                PropertyChangeListener listener = new PropertyChangeListener() {
                    public void propertyChange(PropertyChangeEvent event) {
                        // Let the defaultCloseOperation handle the closing
                        // if the user closed the window without selecting a button
                        // (newValue = null in that case).  Otherwise, close the dialog.
                        if (dialog.isVisible()
                                && (event.getPropertyName().equals(VALUE_PROPERTY))
                                && event.getNewValue() != null
                                && event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
                            dialog.setVisible(false);
                        }
                    }
                };
    
                WindowAdapter adapter = new WindowAdapter() {
                    private boolean gotFocus = false;
    
                    public void windowClosing(WindowEvent we) {
                        pane.setValue(null);
                    }
    
                    public void windowClosed(WindowEvent e) {
                        dialog.removePropertyChangeListener(listener);
                        dialog.getContentPane().removeAll();
                    }
    
                    public void windowGainedFocus(WindowEvent we) {
                        // Once window gets focus, set initial focus
                        if (!gotFocus) {
                            pane.selectInitialValue();
                            gotFocus = true;
                        }
                    }
                };
                dialog.addWindowListener(adapter);
                dialog.addWindowFocusListener(adapter);
                dialog.addComponentListener(new ComponentAdapter() {
                    public void componentShown(ComponentEvent ce) {
                        // reset value to ensure closing works properly
                        pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
                    }
                });
    
                pane.addPropertyChangeListener(listener);
    
                dialog.add(pane);
                //dialog.pack();
                //dialog.setLocationRelativeTo(null);
                dialog.setSize(970, 300); // This is bad idea, use an EmptyBorder instead
                dialog.setLocation(950, 0);
                dialog.setVisible(true);
    
                String pick = null;
                Object value = pane.getInputValue();
                if (value != UNINITIALIZED_VALUE) {
                    pick = value.toString();
                }
    
                return pick;
    
            }
    
        }
    
    }
    

    The reason you're having problems with JFrame is because it's not designed to block the code execution when displayed, a JDialog can, see How to Make Dialogs for more details