使用JOptionPane API的自定义对话框不会被处置 [英] Custom dialog using JOptionPane API won't dispose

查看:168
本文介绍了使用JOptionPane API的自定义对话框不会被处置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been just playing with JOptionPane API to show a custom dialog and I've found a strange situation: when I choose either OK or Cancel option or press Esc key this dialog won't dispose as expected.

事情是,而不是使用此单行显示模式对话框:

The thing is, instead of using this single line to display a modal dialog:

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

我想使用API​​,逐个设置所有参数并显示如下所示的对话框文档(参见 直接使用 部分):

I wanted to use the API, setting all the parameters one by one and displaying a dialog as shown in the docs (see Direct Use section):

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

然而,当我关闭对话框时,我的应用程序一直在运行,即使我将默认关闭操作设置为 DISPOSE_ON_CLOSE ,这让我怀疑对话框没有妥善处理。

However, when I close the dialog my application keeps running, even if I set the default close operation to DISPOSE_ON_CLOSE, and it makes me suspect the dialog is not properly disposed.

以下是 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);
            }
        });
    }
}


推荐答案

好,检查 JOptionPane# createDialog(String title)源代码,结果是对话框没有关闭也没有处理但是隐藏了,当选项窗格的值为 PropertyChangeEvent 时已设置( CANCEL_OPTION NO_OPTION CLOSED_OPTION 我猜):

Well, inspecting JOptionPane#createDialog(String title) source code, it turns out the dialog is not closed nor disposed but hidden instead, and it's done on a PropertyChangeEvent when the option pane's value is set (to CANCEL_OPTION or NO_OPTION or CLOSED_OPTION I guess):

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

尽管有评论states 否则,请关闭对话框,否 WindowEvent 甚至被触发。因此,除非我们明确地这样做,否则对话框将无法正确处理:

Despite the comment that states "Otherwise, close the dialog", no WindowEvent closing the dialog is even fired. Consequently the dialog won't be disposed properly unless we explicitely do so:

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

请注意 WindowListener 附加到 initDialog中的对话框(...)方法只将选项窗格的值设置为 null ,但仍然不会处置对话框。这就是为什么我们仍然需要将默认关闭操作设置为 DISPOSE_ON_CLOSE

Please note on a WINDOW_CLOSING event the WindowListener attached to the dialog within initDialog(...) method will just set the option pane's value to null but still won't dispose the dialog. That's why we still need to set the default close operation to DISPOSE_ON_CLOSE.

这篇关于使用JOptionPane API的自定义对话框不会被处置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆