【问题标题】:Custom dialog using JOptionPane API won't dispose使用 JOptionPane API 的自定义对话框不会处理
【发布时间】:2014-12-10 15:09:30
【问题描述】:

我一直在使用JOptionPane API 来显示自定义对话框,我发现了一个奇怪的情况:当我选择 OKCancel 选项时或按 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);
            }
        });
    }
}

【问题讨论】:

    标签: java swing dispose joptionpane


    【解决方案1】:

    好吧,检查 @987654321 @源代码,事实证明,对话框没有封闭,而是隐藏了,当设置了选项窗格的值时,它是在 @987654326 @上完成的(to @987654327 @or @ @987654327 @or @ @9877654328 @或CLOSED_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 事件中,WindowListener 附加到initDialog(...) 方法中的对话框只会将选项窗格的值设置为null,但仍不会释放对话框。这就是为什么我们仍然需要将默认关闭操作设置为DISPOSE_ON_CLOSE

    【讨论】:

    • JOptionPane 是从 JDialog 派生的一部分,我敢肯定,@kleopatra 的帖子中有几次很好的解释(和相关代码)
    • dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING)); == 终止当前的 JVM,你确定...,
    • @mKorbel:1)谢谢!我没有考虑。我会看看 kleopatra 的帖子。 2)在这种情况下,是的,它将终止当前的 JVM,因为没有更多的窗口(JFrame 不是 JDialog),但这只是为了示例。
    猜你喜欢
    • 2012-08-27
    • 2010-10-21
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多