Say I am making a program that keeps track of people's favorite food. I have a dropdown, as such:
String foods = { "Pizza", "Burgers", "Pasta", "Bacon" };
String favoriteFood = JOptionPane.showInputDialog(null, "What is your favorite food?", "Choice", JOptionPane.QUESTION_MESSAGE, null, foods, foods[0]));
JOptionPane.showMessageDialog(null, favoriteFood);
How do I make a part in the dropdown that is like "Choose now...", but if you click the "Choose now...", it doesn't become your choice? Thank you!
CodePudding user response:
You may do it like this
String[] foods = { "Pizza", "Burgers", "Pasta", "Bacon" };
JComboBox<String> cb = new JComboBox<String>(foods);
cb.getModel().setSelectedItem("Choose now...");
cb.addHierarchyListener(hEv -> {
if((hEv.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 && cb.isShowing()) {
JButton ok = SwingUtilities.getRootPane(cb).getDefaultButton();
ok.setEnabled(cb.getSelectedIndex() >= 0);
cb.addActionListener(aEv -> ok.setEnabled(cb.getSelectedIndex() >= 0));
} });
JPanel p = new JPanel(new GridLayout(0, 1, 0, 8));
p.add(new JLabel("What is your favorite food?"));
p.add(cb);
int choice = JOptionPane.showConfirmDialog(null,
p, "Choice", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
JOptionPane.showMessageDialog(null,
choice == JOptionPane.OK_OPTION? cb.getSelectedItem(): "no choice");
The first challenge is to set a (pre)selected value that is not part of the selectable choices. When you call setSelectedItem
on a non-editable JComboBox
, it will reject any values outside the model. However, we can set the selected value on the model directly, like in cb.getModel().setSelectedItem("Choose now...");
Then, to ensure that we won’t confuse this initial selection with an actual selection, we have to disable the “Ok” button until a choice from the list has been made (cb.getSelectedIndex() >= 0
). To get the “Ok” button itself, we wait until the entire AWT hierarchy has been constructed and get the default button.
CodePudding user response:
A possible solution using the JOptionPane
is shown below. In this code the JDialog
is more or less manually created. The OK button and available options are then pulled from the JOptionPane
and the OK button is only enabled when anything other than 'Choose from...' is selected.
String[] foods = new String[]{"Choose now...", "Pizza", "Burgers", "Pasta", "Bacon"};
JOptionPane pane = new JOptionPane("What is your favorite food?", JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION, null,
null, null);
pane.setWantsInput(true);
pane.setSelectionValues(foods);
pane.setInitialSelectionValue(foods[0]);
// create the dialog and select the initial value
JDialog dialog = pane.createDialog( null, "title" );
pane.selectInitialValue();
// find the OK Button and disable it by default
JPanel buttonPanel = (JPanel) pane.getComponent( 1 );
JButton ok = (JButton) buttonPanel.getComponent( 0 );
ok.setEnabled( false );
// find the JComboBox (the panel holding the available options)
JPanel childPanel = (JPanel) ((JPanel) pane.getComponent( 0 )).getComponent( 0 );
JPanel innerPanel = (JPanel) childPanel.getComponent( 1 );
JComboBox options = (JComboBox) innerPanel.getComponent( 1 );
// add an action listener to the JComboBox; enable the OK button if a valid option is selected
options.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ( options.getSelectedIndex() == 0 ) {
ok.setEnabled( false );
} else {
ok.setEnabled( true );
}
}
});
// show the dialog
dialog.show(); // <--- note this one is deprecated, should probably use: dialog.setVisible( true );
dialog.dispose();
// get the selected value
String value = pane.getInputValue().toString();