【问题标题】:Java - how do I prevent WindowClosing from actually closing the windowJava - 如何防止 WindowClosing 实际关闭窗口
【发布时间】:2011-11-28 15:20:51
【问题描述】:

对大多数人来说,我似乎有相反的问题。我有以下非常标准的代码来查看用户是否想在关闭窗口之前进行一些保存:

  frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
  frame.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent ev) {
      boolean close = true;
         // check some files, asking if the user wants to save
         // YES and NO handle OK, but if the user hits Cancel on any file,
         //   I want to abort the close process     
         // So if any of them hit Cancel, I set "close" to false
      if (close) {
          frame.dispose();
          System.exit(0);
         }
       }            
});

无论我尝试什么,当我退出 windowClosing 时,窗口总是关闭。将 WindowAdapter 更改为 WindowListener 没有任何区别。奇怪的是,文档明确指出“如果程序在处理此事件时没有明确隐藏或处置窗口,则窗口关闭操作将被取消”,但它对我来说不起作用。还有其他方法可以处理框架上的 x 吗? TIA

【问题讨论】:

  • 我敢打赌,如果您通过创建sscce 尽可能简化您的问题,那么您肯定会发现某个地方的错误。如果它没有变得明显,那么您可以发布 sscce,我们可以对其进行处理,以便更好地为您提供帮助。
  • 根据提供的代码,您设置close 变量的逻辑可能是错误的。由于它默认为 true ,因此您似乎没有正确重置它。你打印出 if 语句之前的值了吗?
  • 我刚刚遇到了另一种情况,如果使用 Netbeans (8.0),可能会导致这些症状。 Design View 自动生成的代码将添加自己的默认关闭操作,该操作可以覆盖人工生成代码中指定的行为。这可以在 JDialog 属性框中进行编辑。 (尽管这不是保罗问题的答案,但为寻求类似问题解决方案的后代留下此评论。)

标签: java swing jframe windowlistener


【解决方案1】:

我刚刚尝试了这个最小的测试用例:

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class Test {

    public static void main(String[] args) {
        final JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent ev) {
                //frame.dispose();
            }
        });
        frame.setVisible(true);
    }

}

如果我保留 dispose 调用的注释并点击关闭按钮,则窗口不会退出。取消注释并点击关闭按钮,窗口关闭。

我不得不猜测您设置“关闭”变量的逻辑有问题。尝试仔细检查。

【讨论】:

  • 谢谢大家!我找到了,确实是我的问题。知道这个简单的案例很有帮助!
  • 请学习 java 命名约定并遵守它们 - 不过,为最短的测试用例 +1 :-)
  • 设置默认关闭操作对我来说很关键,如上面的演示中所列,其他答案中也提到过。
  • 干净的答案。 +1
【解决方案2】:

这是关键,我认为:frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 使我编写的测试用例有所不同。

【讨论】:

  • 这是整个事情的关键。 EXIT_ON_CLOSE 似乎覆盖了其他答案中提到的所有内容。谢谢本!
【解决方案3】:

不知道你的问题在哪里,

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ClosingFrame extends JFrame {

    private JMenuBar MenuBar = new JMenuBar();
    private JFrame frame = new JFrame();
    private static final long serialVersionUID = 1L;
    private JMenu File = new JMenu("File");
    private JMenuItem Exit = new JMenuItem("Exit");

    public ClosingFrame() {
        File.add(Exit);
        MenuBar.add(File);
        Exit.addActionListener(new ExitListener());
        WindowListener exitListener = new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                int confirm = JOptionPane.showOptionDialog(frame,
                        "Are You Sure to Close this Application?",
                        "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                        JOptionPane.QUESTION_MESSAGE, null, null, null);
                if (confirm == JOptionPane.YES_OPTION) {
                    System.exit(1);
                }
            }
        };
        frame.addWindowListener(exitListener);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setJMenuBar(MenuBar);
        frame.setPreferredSize(new Dimension(400, 300));
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);
    }

    private class ExitListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            int confirm = JOptionPane.showOptionDialog(frame,
                    "Are You Sure to Close this Application?",
                    "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE, null, null, null);
            if (confirm == JOptionPane.YES_OPTION) {
                System.exit(1);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ClosingFrame cf = new ClosingFrame();
            }
        });
    }
}

【讨论】:

  • 不要使用幻数。 confirm == 0 是什么意思?为了便于理解,您应该使用confirm == JOptionPane.YES_OPTION
【解决方案4】:

对于这件事的处理:
如果用户选择是,则在该if else 的花括号内使用setDefaultCloseOperation(DISPOSE_ON_CLOSE);

如果选择取消,则使用setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

考虑例子:

int safe = JOptionPane.showConfirmDialog(null, "titleDetails!",  "title!!", JOptionPane.YES_NO_CANCEL_OPTION);

if(safe == JOptionPane.YES_OPTION){
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);//yes

} else if (safe == JOptionPane.CANCEL_OPTION) {
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);//cancel
} else {
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);//no
}

【讨论】:

  • 谢谢你如果我把这段代码放在关闭事件中会阻止对话框关闭
【解决方案5】:

不确定您的问题出在哪里,但这对我有用!

frame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent evt) {
                            int res=JOptionPane.showConfirmDialog(null,
                                    "Do you want to exit.?");
                            if(res==JOptionPane.YES_OPTION){
                                    Cal.this.dispose();
                            }
            }                               
        });

【讨论】:

    【解决方案6】:

    为了解决同样的问题,我尝试了本文的第一个答案。 作为单独的应用程序,它可以工作,但在我的情况下不行。 也许区别在于 JFrame(答案)和 FrameView(我的情况)。

    public class MyApp extends SingleFrameApplication { // application class of my project
      ...
      protected static MyView mainForm; // main form of application
      ... 
    }  
    public class MyView extends FrameView {
        ...
        //Adding this listener solves the problem. 
        MyApp.getInstance().addExitListener(new ExitListener() {
    
          @Override
          public boolean canExit(EventObject event) {
            boolean res = false;
            int reply = JOptionPane.showConfirmDialog(null,
                    "Are You sure?", "", JOptionPane.YES_NO_OPTION);
            if (reply == JOptionPane.YES_OPTION) {
              res = true;
            }
            return res;
          }
          @Override
          public void willExit(EventObject event) {
          }
        });
        ...
    }   
    

    【讨论】:

      【解决方案7】:

      setDefaultCloseOperation() 方法有助于解决问题。https://chortle.ccsu.edu/java5/Notes/chap56/ch56_9.html

      查看此链接

      【讨论】:

      • 虽然只有链接的答案是答案,但最好将解释放在答案中并使用链接作为参考,因为链接可能会中断。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多