作为一个弹出窗口和下拉菜单的简单Java GUI

5
我以前从未编写过Java GUI。这次我也可以跳过它,使用 args 作为UI(用户界面)。 但我想知道是否有一种简单的方法来创建一个小型GUI,让用户选择其中一个选项。 换句话说,要实现 askUser() 函数,使用户可以从下拉菜单中选择并按“确定”。 我花了一些时间学习这个主题,但甚至不确定我需要哪种类型的GUI来完成此任务。JFrame?JPanel?Jmenu?谢谢。
以下是所需函数的示例。
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;
    }
}

更新: 我使用Netbeans,如果这可能会有所不同。

3个回答

15

最简单的选项是使用 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;
                }

            }
        });
    }
}

通过阅读如何制作对话框,您可以了解更多信息。

根据反馈更新

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;
        }
    }
}

谢谢。但我需要在main()中得到结果。我使用JOptionPane找到了一个解决方案。但是为了理解,如果我使用您的解决方案,我如何在main()中获取结果的String - Serg
你遇到的问题是试图从事件分派线程之外访问UI(因为main不在EDT中启动)。这会带来许多问题。请检查更新以获取可能的解决方案。真正的解决方案是在main方法中使用SwingUtilties#invokeLater将您带入EDT,并继续在那里启动应用程序的其余部分。 - MadProgrammer

2

在询问后,我找到了这个解决方案。为了让它更简单,askUser() 返回一个 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


1
永远不要在事件分派线程之外创建/修改任何UI组件,这是一种不好的做法,会让你陷入沮丧和秃头的泥潭中(因为你会拔光头发)。 - MadProgrammer
@MadProgrammer,我在维基百科上读到了关于EDT的内容,但我必须承认我不理解这种解决方案在处理如此简单的任务时可能会遇到什么问题。你能给出一个它失败的例子吗? - Serg
主要问题是你可能会得到脏数据或突变异常(因为模型正在被两个线程同时更新)。虽然这只是一个简单的例子,但这是一种不好的做法。如果你不费心去消除它,它将以难以调试的方式回来困扰你(比如线程竞争和死锁问题)。 - MadProgrammer
对于一个失败的示例,创建一个带有行排序器的JTable。使用自定义的表格模型,从EDT外部填充它,允许模型触发更新事件。你还可以尝试使用两个或更多线程以随机间隔更新文本区域(作为我所知的几个示例)。 - MadProgrammer

2
如果您想创建一个Swing GUI,使用像NetBeans这样的IDE可以让您简单地使用WYSIWYG gui designer,因此您只需将GUI元素拖放到指定位置,然后在NetBeans输出的GUI代码周围添加逻辑代码。
当然,它并不是要依赖它来“为您构建GUI”,但它确实很好地为您设置了一个基础来进行工作。您还可以通过阅读和使用NetBeans为GUI生成的代码来学习很多关于Swing的知识。
我发现这是一个很好的加速器,可以帮助您开始设计Swing应用程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接