向JOptionPane添加一个额外的自定义按钮



我正在尝试显示一个框架,该框架向用户提供项目列表,用户可以从中(从组合菜单中)进行选择,现在用户可以选择ok来选择所选项目,或者按cancel,返回null。这些是给我的默认选项。

这是我的代码片段:

Set<ICarOption> optionSet = spec.getCarOptions(category);
// If the category is not mandatory, create a makeshift option object to skip.
if(!category.getMandatory())    optionSet.add(new CarOption("skip"));
ICarOption[] optionArray = optionSet.toArray(new ICarOption[optionSet.size()]);
ICarOption selectedOption = (ICarOption)JOptionPane.showInputDialog(
                frame,
                "Choose one of the following options for Category " + category + ".n" + 
                "If skip is available, you may choose it to skip this category.",
                "Select a feature",
                JOptionPane.QUESTION_MESSAGE, 
                null, 
                optionArray, 
                optionArray[0]);

这段代码发生在for循环中,在类别上迭代,其中类别并不总是强制性的。这意味着,如果我想让用户可以选择跳过一个类别,我会为组合框实现另一个名为skip的选项,如果选择了这个选项,我会相应地跳过它。但这感觉像是一种肮脏的做事方式(从我定义的ICarOption对象的意义上来说,跳过根本不是一个选项),如果类别是强制性的,我宁愿有一个名为跳过的按钮,它是灰色的(不可点击),而当类别不是强制性的时,它是可用的。

我在这里看到了一些例子:http://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html

这似乎表明我应该用一个自定义的按钮列表来替换我的组合框,这不是我想要的。我需要3个按钮(好,跳过,取消),以及项目列表。

更新:为了说明我的GUI会是什么样子:

  1. 框架制作完成
  2. 在对话框窗口中,您可以看到ICarOption对象的组合框(下拉列表)
  3. 窗口上还有3个按钮:OK、SKIP和CANCEL
  4. 如果该类别是强制性的,则SKIP将变灰
  5. 如果选择了OK,则组合框中当前选定的项目将被赋予selectedOption变量
  6. 如果选择了CANCEL,则selectedOption==null
  7. 如果选择了"跳过",则将跳过此类别(continue;)

这意味着在输入窗口上,我需要看到一个包含项目和3个按钮的组合框。

-删除子问题-

更新2:我刚刚意识到我也不能使用JButton,因为我需要在actionListener中执行相当多的操作,并且它要求变量是final,其中一些不能是final。

目前我的代码如下:

JPanel panel = new JPanel();
JComboBox<ICarOption> optionsBox = new JComboBox<ICarOption>();
panel.add(optionsBox);
for(ICarOption option : spec.getCarOptions(category)){
    optionsBox.addItem(option);
}
Object[] options = { "Select option", "Skip", "Cancel" };
int selected = JOptionPane.showOptionDialog(
                panel,
                "Choose one of the following options for Category " + category + ".n" + 
                "If skip is available, you may choose it to skip this category.",
                "Select option",
                JOptionPane.YES_NO_CANCEL_OPTION, 
                JOptionPane.INFORMATION_MESSAGE, null, 
                options, 
                options[0]);
if(selected == JOptionPane.NO_OPTION)   continue;
if(selected == JOptionPane.CANCEL_OPTION)   throw new UnavailableException();
if(selected == JOptionPane.YES_OPTION){
    ...
}

灵感来自:Java:showInputDialog 中的自定义按钮

这个问题是我现在没有办法控制跳过按钮,因为它是在创建窗口的那一刻创建的。

更新3:它现在起作用了,但我并不为自己的表现感到骄傲。

        JPanel panel = new JPanel();
        JComboBox<ICarOption> optionsBox = new JComboBox<ICarOption>();
        panel.add(optionsBox);
        for(ICarOption option : spec.getCarOptions(category)){
            optionsBox.addItem(option);
        }
        int selected;
        if(!category.getMandatory()){
            Object[] options = { "Select option", "Cancel", "Skip" };
            selected = JOptionPane.showOptionDialog(
                    panel,
                    "Choose one of the following options for Category " + category + ".n" + 
                    "If skip is available, you may choose it to skip this category.",
                    "Select option",
                    JOptionPane.YES_NO_CANCEL_OPTION, 
                    JOptionPane.INFORMATION_MESSAGE, null, 
                    options, 
                    options[0]);
        }
        else{
            Object[] options = { "Select option", "Cancel" };
            selected = JOptionPane.showOptionDialog(
                    panel,
                    "Choose one of the following options for Category " + category + ".n" + 
                    "If skip is available, you may choose it to skip this category.",
                    "Select option",
                    JOptionPane.YES_NO_OPTION, 
                    JOptionPane.INFORMATION_MESSAGE, null, 
                    options, 
                    options[0]);
        }
        // careful! CANCEL_OPTION means skip has been pressed and NO_OPTION means cancel
        if(selected == JOptionPane.CANCEL_OPTION)   continue;
        if(selected == JOptionPane.NO_OPTION)   throw new UnavailableException();
        if(selected == JOptionPane.YES_OPTION){
            ...
        }

那里肯定有大量重复的代码,但这是一种比将skip作为对象传递更好的工作方式。

更新4:将重复部分更改为以下内容:

        ArrayList<Object> tempList = new ArrayList<Object>();
        int optionType;
        tempList.add("Select option");
        tempList.add("Cancel");
        if(!category.getMandatory()){
            tempList.add("Skip");
            optionType = JOptionPane.YES_NO_CANCEL_OPTION;
        }
        else    optionType = JOptionPane.YES_NO_OPTION;
        Object[] options = tempList.toArray(new Object[tempList.size()]);
        int selected = JOptionPane.showOptionDialog(
                panel,
                "Choose one of the following options for Category " + category + ".n" + 
                        "If skip is available, you may choose it to skip this category.",
                        "Select option",
                        optionType, 
                        JOptionPane.INFORMATION_MESSAGE, null, 
                        options, 
                        options[0]);

因此,我将初始化存储在ArrayList中,然后将其转换为数组。这对我来说开始很好了。:p我不得不说我严重低估了这个问题。我只是想从向我的项目列表中添加一个对象来跳过,变成有一个跳过按钮。不知怎么的,我花了几个小时才"做好"。

小编辑(请注意用户3469755):我很抱歉,我刚刚看了一些以前的编辑,突然发现了一些东西。你最初的回答为我提供了我一直想要的。。。我在使用监听器时遇到的问题是,我在"确定"按钮中添加了很多功能,但它真正需要做的只是将下拉列表中的选定项分配给参数"selectedOption"。我只需要在showOptionDialog和处理跳过和取消的部分之后添加其余功能,因为我确信在这一点上,已经选择了一个项目,参数将包含一个对象。我有时会非常密集。。

您链接的文档非常直接:

options:将显示在对话框底部的选项按钮集的更详细描述。options参数的常用值是一个字符串数组。但参数类型是对象的数组

因此,您只需要定义一些您选择的JButton,将它们封装在一个数组中(如字符串数组),然后将它们传递到JOptionPane.showOptionDialog方法中。例如,为了实现JButton的交互性,您可以使用一些Mouseclick侦听器,并将其变灰,使其不可点击(不同!)您可以使用setEnabled()更改JButton属性;

以下是我写的完整示例:

    JButton jbt_ok = new JButton("OK");
    JButton jbt_skip = new JButton("Skip");
    JButton jbt_cancel = new JButton("Cancel");
    boolean greyOutSkipButton = true;
    jbt_ok.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            System.out.println("OK was clicked");
        }
    });
    jbt_cancel.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            System.out.println("Cancel was clicked");
        }
    });
    if(greyOutSkipButton)
        jbt_skip.setEnabled(false);
    else
        jbt_skip.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Skip was clicked");
            }
        });
    Object[] options = {jbt_ok, jbt_skip, jbt_cancel};
    JOptionPane.showOptionDialog(null, "Click OK to continue", "Warning",
            JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
            null, options, options[0]);

主要问题:

如果类别不是强制性的,我会添加一个单独的按钮,并在该按钮上添加ActionListener,它将跳过该类别并转到下一个。

子问题:

您需要获得用户的响应。

Object[] options = { "OK", "CANCEL" };
Object answer = JOptionPane.showOptionDialog(null, "Click OK to continue", "Warning",
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
switch ((String) answer){
case "OK":
    //do stuff

相关内容

  • 没有找到相关文章