I'm trying to show a frame that presents a user with a list of items, which the user can choose from (from a combobox menu) and the user is now able to select ok to choose the selected item, or press cancel, which returns null. These are the default options given to me.
Here's my code snippet:
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]);
This code happens in a for loop, iterating over categories, where the category is not always mandatory. This means that if I want to allow a user to have the option to skip a category, I implement another option to the combobox called skip, and if that is selected, I will skip it accordingly. But this feels like a dirty way of doing things (skip is not an option at all in the sense of my defined ICarOption object) and I'd rather have a button called skip that's greyed out (not clickable) if the category is mandatory and available when the category is not mandatory.
I've seen some examples here: http://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html
It seems to show that I should replace my combobox with a self defined list of buttons, which is not what I want. I need to have 3 buttons (ok, skip, cancel), as well as the list of items.
UPDATE: To illustrate what my GUI would look like:
- The frame gets made.
- On the dialog window you see a combobox (dropdown list) of ICarOption objects
- There are also 3 buttons on the window: OK, SKIP and CANCEL
- If the category was mandatory, SKIP will be greyed out.
- If OK is selected, the currently selected item in the combobox will be given to the selectedOption variable
- If CANCEL is selected, selectedOption == null
- If SKIP is selected, this category will be skipped (continue;)
This means that on the input window I need to see a combobox with items and 3 buttons.
-Removed the subquestion-
UPDATE2: I just realized I can't use JButton either because I need to perform quite a few actions within the actionListener, and it requires the variables to be final, some of which cannot be final.
Currently my code looks like this:
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){
...
}
Inspiration gotten from: Java: Custom Buttons in showInputDialog
The problem with this is that I now don't have a way of controlling the skip button, as it gets created the moment the window gets created.
UPDATE3: It works now, but I'm not proud of how I did it..
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){
...
}
There's definitely a chunk of duplicate code there, but this is a way that works and feels better than passing skip as an object.
UPDATE4: Changed the duplicate part to the following:
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]);
So I store the initialization in an ArrayList and convert it to an array afterwards. This is starting to look pretty good to me. :p I have to say I severely underestimated this problem. I simply wanted to change from adding an object to my list of items in order to skip, to having a skip button. That somehow took me several hours to do 'properly'.
small edit (note to user3469755): My apologies, I just looked over some of the previous edits and something just hit me. Your original answer provided me with what I wanted all along... The problem I had with using the listener is that I put a lot of the functionality in the OK-button, but all it really needed to do was to assign the selected item from the dropdown list to the parameter 'selectedOption'. The rest of the functionality I simply had to add after the showOptionDialog and the part where skip and cancel gets handled, as I'm sure that at that point, an item has been selected and the parameter will hold an object. I can be incredibly dense sometimes..