使用JOptionPane API的自定义对话框不会被处置

时间:2014-12-10 15:09:31

标签: java swing dispose joptionpane

我一直在玩JOptionPane API来显示自定义对话框,而且我发现了一个奇怪的情况:当我选择 OK 时取消选项或按 Esc 键,此对话框不会按预期处理。

问题是,而不是使用这一行来显示模态对话框:

JOptionPane.showConfirmDialog( null
                            , "The quick brown fox jumps over the lazy dog."
                            , "New Dialog"
                            , JOptionPane.OK_CANCEL_OPTION
                            , JOptionPane.PLAIN_MESSAGE);

我想使用API​​,逐个设置所有参数并显示docs中显示的对话框(请参阅 直接使用 部分) :

 JOptionPane pane = new JOptionPane(arguments);
 pane.set.Xxxx(...); // Configure
 JDialog dialog = pane.createDialog(parentComponent, title);
 dialog.show();

但是,当我关闭对话框时,即使我将默认关闭操作设置为DISPOSE_ON_CLOSE,我的应用程序仍会继续运行,这让我怀疑对话框没有正确处理。

下面是MCVE玩:

import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class Demo {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JOptionPane optionPane = new JOptionPane();
                optionPane.setMessage("The quick brown fox jumps over the lazy dog.");
                optionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
                optionPane.setMessageType(JOptionPane.PLAIN_MESSAGE);

                JDialog dialog = optionPane.createDialog("New Dialog");
                dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                dialog.setVisible(true);
            }
        });
    }
}

1 个答案:

答案 0 :(得分:2)

嗯,检查JOptionPane#createDialog(String title)源代码,结果是对话框没有关闭也没有被隐藏,而是隐藏了,当选项窗格显示时,它在PropertyChangeEvent上完成了设置了价值(我估计为CANCEL_OPTIONNO_OPTIONCLOSED_OPTION):

public class JOptionPane extends JComponent implements Accessible {

    ...

     // The following method is called within 'createDialog(...)'
     // in order to initialize the JDialog that will be retrieved.

    private void initDialog(final JDialog dialog, int style, Component parentComponent) {
        ...
        final PropertyChangeListener listener = new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent event) {
                // Let the defaultCloseOperation handle the closing
                // if the user closed the window without selecting a button
                // (newValue = null in that case).  Otherwise, close the dialog.
                if (dialog.isVisible() && event.getSource() == JOptionPane.this &&
                        (event.getPropertyName().equals(VALUE_PROPERTY)) &&
                        event.getNewValue() != null &&
                        event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
                    dialog.setVisible(false);
                }
            }
        };

        WindowAdapter adapter = new WindowAdapter() {
            private boolean gotFocus = false;
            public void windowClosing(WindowEvent we) {
                setValue(null);
            }

            public void windowClosed(WindowEvent e) {
                removePropertyChangeListener(listener);
                dialog.getContentPane().removeAll();
            }

            public void windowGainedFocus(WindowEvent we) {
                // Once window gets focus, set initial focus
                if (!gotFocus) {
                    selectInitialValue();
                    gotFocus = true;
                }
            }
        };
        dialog.addWindowListener(adapter);
        dialog.addWindowFocusListener(adapter);
        ...
    }
}

尽管注释声明"否则,关闭对话框" ,没有WindowEvent关闭对话框甚至被触发。因此,除非我们明确地这样做,否则对话不会被妥善处理:

    JDialog dialog = optionPane.createDialog("New Dialog");
    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    dialog.setVisible(true);
    dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING));

请注意,在WINDOW_CLOSING事件中,initDialog(...)方法中对话框附带的WindowListener只会将选项窗格的值设置为null,但仍会赢得& #39; t配置对话框。这就是为什么我们仍然需要将默认关闭操作设置为DISPOSE_ON_CLOSE