【问题标题】:Simple Java GUI as a popup window and drop-down menu简单的 Java GUI 作为弹出窗口和下拉菜单
【发布时间】:2012-11-04 16:27:02
【问题描述】:

我从来不用用java写GUI。这次我也可以跳过它,使用args 作为 UI(用户界面)。 但我想知道是否有一种简单的方法可以创建一个小 GUI 让用户选择其中一个选项。 换句话说,要实现askUser() 功能,用户可以从下拉菜单中选择并按“确定”。 我花了一些时间学习这个主题,但我什至不确定我是否知道我需要哪种类型的 GUI 来完成这项任务。框架?面板?菜单?谢谢。

这是所需功能的示例。

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,如果这能有所作为的话。

【问题讨论】:

    标签: java swing popup jcombobox joptionpane


    【解决方案1】:

    如果你想创建一个 Swing GUI,使用像 NetBeans 这样的 IDE 可以让你使用 WYSIWYG gui designer 变得简单,所以你可以将你的 GUI 元素拖放到适当的位置,然后在 GUI 周围添加你的逻辑代码NetBeans 输出的代码。

    “为您构建 gui”当然不是可以依赖的东西,但它确实可以很好地为您的工作奠定基础。您还可以通过阅读和使用 NetBeans 为 GUI 生成的代码来学习很多关于 Swing 的知识。

    我发现这是开始设计 Swing 应用程序的一个很好的加速器。

    【讨论】:

      【解决方案2】:

      最简单的选择是使用JOptionPane API

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

      您可以通过阅读How to Make Dialogs了解更多信息

      已根据反馈更新

      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
      • 您遇到的问题是您尝试从事件调度线程外部访问 UI(因为 main 未在 EDT 内启动)。这带来了许多问题。检查更新以获取可能的解决方案。真正的解决方案是在 main 方法中使用 SwingUtilties#invokeLater 让您进入 EDT 并继续在那里启动其余的应用程序
      【解决方案3】:

      询问后我找到了这个解决方案。为了更简单,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;
          }
      }
      

      【讨论】:

      • 永远不要在 Event Dispatching Thread 之外创建/修改任何 UI 组件,这是不好的做法,并且会导致您陷入沮丧和秃顶的滑坡(当您扯掉头发时)
      • @MadProgrammer,我在 wiki 上读到了 EDT,我必须承认,我不明白这个解决方案会给如此简单的任务带来什么麻烦。你能举一个失败的例子吗?
      • 主要问题是您最终可能会遇到脏油漆或变异异常(因为模型开始由两个线程同时更新)。虽然这是一个简单的例子,但这是一个不好的做法,如果你不努力根除这种做法,它会以难以调试的方式回来并困扰你(你好线程竞争和死锁问题)
      • 对于失败的示例,使用行排序器创建你自己 JTable。使用自定义表模型,从 EDT 外部填充它,允许模型触发更新事件。作为我知道的几个示例,您还可以尝试让两个或更多线程来更新文本区域(使用随机间隔)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多