5

I never had to write GUI in java. This time I can also skip it and use args as UI (user interface). But I wonder if there is a simple way to create a small GUI to let the user select one of the options. In other words, to implement the askUser() function where user can select from a drop-down menu and press "ok". I spend some time learning this topic, but not even sure that I know which type of GUI i need for this task. JFrame? JPanel? Jmenu? Thanks.

Here is an example of the desired function.

package trygui;

public class Main {

    public static void main(String[] args) {
        String[] choices = new String[]{"cats", "dogs"};
        int choice = askUser(choices);
        System.out.println("selected: " + choices[choice]);
    }

    static int askUser(String[] choices) {
        // create pop-up dialog
        return 0;
    }
}

Update: I use Netbeans, if this can make difference.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Serg
  • 13,470
  • 8
  • 36
  • 47

3 Answers3

15

The simplest option would be to use the JOptionPane API

enter image description here

public class TestOptionPane03 {

    public static void main(String[] args) {
        new TestOptionPane03();
    }

    public TestOptionPane03() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JPanel panel = new JPanel();
                panel.add(new JLabel("Please make a selection:"));
                DefaultComboBoxModel model = new DefaultComboBoxModel();
                model.addElement("Chocolate");
                model.addElement("Strewberry");
                model.addElement("Vanilla");
                JComboBox comboBox = new JComboBox(model);
                panel.add(comboBox);

                int result = JOptionPane.showConfirmDialog(null, panel, "Flavor", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                switch (result) {
                    case JOptionPane.OK_OPTION:
                        System.out.println("You selected " + comboBox.getSelectedItem());
                        break;
                }

            }
        });
    }
}

You can find out more by having a read through How to Make Dialogs

UPDATED with feedback

public class TestOptionPane03 {

    public static void main(String[] args) {
        String choice = ask("Chocolate", "Strewberry", "Vanilla");
        System.out.println("You choose " + choice);
    }

    public static String ask(final String... values) {

        String result = null;

        if (EventQueue.isDispatchThread()) {

            JPanel panel = new JPanel();
            panel.add(new JLabel("Please make a selection:"));
            DefaultComboBoxModel model = new DefaultComboBoxModel();
            for (String value : values) {
                model.addElement(value);
            }
            JComboBox comboBox = new JComboBox(model);
            panel.add(comboBox);

            int iResult = JOptionPane.showConfirmDialog(null, panel, "Flavor", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
            switch (iResult) {
                case JOptionPane.OK_OPTION:
                    result = (String) comboBox.getSelectedItem();
                    break;
            }

        } else {

            Response response = new Response(values);
            try {
                SwingUtilities.invokeAndWait(response);
                result = response.getResponse();
            } catch (InterruptedException | InvocationTargetException ex) {
                ex.printStackTrace();
            }

        }

        return result;

    }

    public static class Response implements Runnable {

        private String[] values;
        private String response;

        public Response(String... values) {
            this.values = values;
        }

        @Override
        public void run() {
            response = ask(values);
        }

        public String getResponse() {
            return response;
        }
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you. But I needed the result in the main(). I found a solution using JOptionPane. But just to understand, how could I get the resulting `String` in the main() if I use your solution? – Serg Nov 16 '12 at 00:29
  • The problem you have there is your attempting to access the UI from out side the Event Dispatching Thread (as `main` is not launched within the EDT). This brings a number of issues. Check update for possible solution. The real solution would be to use `SwingUtilties#invokeLater` in the `main` method to get you into the EDT and continue launching the remainder of you application there – MadProgrammer Nov 16 '12 at 00:39
  • @MadProgrammer [for notified about initial thread in another answer here](http://stackoverflow.com/a/12643642/714968) – mKorbel Nov 16 '12 at 07:00
2

If you want to create a Swing GUI, using an IDE like NetBeans gives you the simplicity of using a WYSIWYG gui designer, so you can just drag and drop your GUI elements into place, and then add your logic code around the GUI code that NetBeans outputs.

It certainly isn't something to rely on to "build the gui for you", but it does do a great job of setting up the foundation for you to work with. You can also learn a lot about Swing just by reading through and working with the code that NetBeans generates for the GUI.

I find this a great accelerator in getting started designing Swing apps.

cam
  • 778
  • 6
  • 9
2

After asking I found this solution. To make it simpler, the askUser() returns String.

package trygui;

import javax.swing.JOptionPane;

public class Main {

    public static void main(String[] args) {
        String[] choices = new String[]{"cats", "dogs"};
        String choice = askUser(choices);
        System.out.println("selected: " + choice);
    }

    static String askUser(String[] choices) {
        String s = (String) JOptionPane.showInputDialog(
                null,
                "make your choice",
                "Try GUI",
                JOptionPane.PLAIN_MESSAGE,
                null,
                choices,
                choices[0]);
        return s;
    }
}

enter image description here

Serg
  • 13,470
  • 8
  • 36
  • 47
  • 1
    NEVER create/modify ANY UI COMPONENT out side the Event Dispatching Thread, it is bad practice and will lead you down a slippery slope of frustration and baldness (as you tear your hair out) – MadProgrammer Nov 16 '12 at 00:41
  • @MadProgrammer, I read about EDT in wiki, and I must admit that I don't understand what troubles can this solution cause for such a simple task. Can you give an example in which it fails? – Serg Nov 16 '12 at 00:49
  • The main problem is you can end up with dirty paints or mutate exceptions (as a model is begin updated by two threads simultaneously). While it's a simple example, it's bad practice, a practice that if you don't take the pains to eradicate, will come back and haunt you in ways which are difficult to debug (hello Thread race and deadlock issues) – MadProgrammer Nov 16 '12 at 00:54
  • For an example where it fails, create you're self `JTable` with a row sorter. Using a custom table model, populate it from outside the EDT, allowing the model to fire update events. You could also try and get two or more threads to update a text area (using random intervals) as a couple of examples I know – MadProgrammer Nov 16 '12 at 01:08
  • 1
    @Serg [no issue to simulating EDT lacks here](http://stackoverflow.com/a/12643642/714968) – mKorbel Nov 16 '12 at 07:10