如何制作具有不可选择的预设选项的 JOptionPane 下拉列表?

How do I make a JOptionPane dropdown that has a preset option that is not choosable?

假设我正在制作一个程序来跟踪人们最喜欢的食物。我有一个下拉列表,如下所示:

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

如何在类似于“立即选择...”的下拉列表中创建一个部分,但是如果您单击“立即选择...”,它不会成为您的选择?谢谢!

使用 JOptionPane 的可能解决方案如下所示。在此代码中,JDialog 或多或少是手动创建的。然后从 JOptionPane 中拉出确定按钮和可用选项,只有在选择 'Choose from...' 以外的任何内容时才启用确定按钮。

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

你可以这样做

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

第一个挑战是设置不属于可选选项的(预)选值。当您在不可编辑的 JComboBox 上调用 setSelectedItem 时,它将拒绝模型外的任何值。但是,我们可以直接在模型上设置所选值,如 cb.getModel().setSelectedItem("Choose now...");

然后,为了确保我们不会将此初始选择与实际选择混淆,我们必须禁用“确定”按钮,直到从列表中做出选择 (cb.getSelectedIndex() >= 0)。要获得“确定”按钮本身,我们要等到整个 AWT 层次结构都已构建并获得默认按钮。