JFrame关闭时退出Java

67

我不明白如何使用这段代码:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

点击窗口上的x按钮来关闭程序。


7
遗憾的是,使用JFrame.EXIT_ON_CLOSE的可怕之处在于,一旦所有的jframe都关闭了,它基本上会调用System.exit(0)来终止所有其他未完成的线程!哇! - rogerdpack
2
如果您正在使用一个框架(类扩展框架),则可以使用以下代码设置关闭操作:this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - Jaimin Patel
如果您知道有未完成的线程,您可以捕获“关闭”事件并在允许其终止之前弹出确认消息,对吧? @rogerdpack - Mauricio Gracia Gutierrez
可能是从哪个窗口的关闭事件触发的?它如何知道这是最后一个,而其他线程仍在运行?这并不是微不足道的问题... - rogerdpack
8个回答

101

您需要这一行代码

frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

当你按下 JFrame 窗口的 X 按钮时,默认行为相当于

frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);

所以几乎所有的情况下,在创建JFrame时你都需要手动添加那行代码。

我目前正在使用WindowConstants中的常量,例如WindowConstants.EXIT_ON_CLOSE,而不是直接在JFrame中声明相同的常量,因为前者更能体现意图。


2
正确识别框架的默认操作/行为会得到+1分。另一方面,通常最好确保没有其他非守护线程在运行,并将框架退出操作设置为JFrame.DISPOSE_ON_CLOSE - Andrew Thompson
我的 IDE 告诉我应该使用 WindowConstants.EXIT_ON_CLOSE。 - Daniel Kaplan
1
可以的,你可以使用两者,因为它们对于每个常量具有相同的整数值,但是是的,WindowConstants接口已经被引入来替换在JFrame中直接声明的常量,因为它更好地反映了意图。 - Jaime Hablutzel
1
如果您正在使用Frame(类扩展Frame),则请使用this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - Jaimin Patel

7
如果没有它,JFrame 将被关闭。窗体会关闭,但应用程序会继续运行。

1
也许原帖作者想尝试一下这段代码,它创建了3个框架并设置 JFrame.DISPOSE_ON_CLOSE。该行为与设置 JFrame.EXIT_ON_CLOSE 时不同。 - Andrew Thompson
3
实际上,我认为Jaime是到目前为止唯一完全正确的人。如果一个框架被丢弃了并且没有非守护线程在运行,JRE 退出。 - Andrew Thompson
@Andrew Thompson,请查看我的与IDE相关的帖子。 - mKorbel
@Andrew Thompson 哦,你说得对,我忘了Dispose了,我删除了我的pip-pip-pip。 - mKorbel
根据Javadoc中的setDefaultCloseOperation,“注意:当Java虚拟机(VM)中的最后一个可显示窗口被处理时,VM可能会终止。有关更多信息,请参见AWT线程问题。”因此,它并没有保证,但可能会发生。 - Jeff Storey

5
调用setDefaultCloseOperation(EXIT_ON_CLOSE)会使应用程序在接收到操作系统发来的关闭窗口事件时退出。当您按下窗口上的关闭(X)按钮时,操作系统会生成一个关闭窗口事件并发送给Java应用程序。该关闭窗口事件将由Java应用程序中的AWT事件循环处理,以响应事件退出应用程序。
如果您不调用此方法,则AWT事件循环可能不会响应关闭窗口事件而使应用程序在后台运行。

1
刚刚修复了。 - Brian Coleman
感谢您的编辑。不幸的是,由于网站软件声称此条目未经过编辑,我似乎无法撤销反对票或添加赞成票。 :( - Andrew Thompson

3

我花了相当多的时间在互联网上寻找一个优雅的解决方案。通常情况下,我发现有很多相互矛盾的信息。

最终,我得到了以下解决方案:

  1. Do not use EXIT_ON_CLOSE as this can leave resources behind;
  2. Do use something like the following in the JFrame initialization:

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    
  3. The real discovery was how to actually dispatch a window message to the JFrame. As an example, as part of your JMenuItem for exiting the application, use the following, where the function getFrame() returns a reference to the JFrame:

    public class AppMenuFileExit extends JMenuItem implements ActionListener
    {
        // do your normal menu item code here
    
          @Override
          public void actionPerformed(ActionEvent e)
          {
            WindowEvent we;
            we = new WindowEvent((Window) App.getFrame(), WindowEvent.WINDOW_CLOSING);
    
            App.getFrame().dispatchEvent(we);
          }
    }
    

    JFrame is a subclass of Window so may be cast to Window for this purpose.

  4. And, have the following in your JFrame class to handle Window messages:

    public class AppFrame extends JFrame implements WindowListener
    {
      // Do all the things you need to for the class
    
      @Override
      public void windowOpened(WindowEvent e)
      {}
      @Override
      public void windowClosing(WindowEvent e)
      {/* can do cleanup here if necessary */}
    
      @Override
      public void windowClosed(WindowEvent e)
      {
        dispose();
        System.exit(0);
      }
      @Override
      public void windowActivated(WindowEvent e)
      {}
      @Override
      public void windowDeactivated(WindowEvent e)
      {}    
      @Override
      public void windowDeiconified(WindowEvent e)
      {}
      @Override
      public void windowIconified(WindowEvent e)
      {}
    }
    

1
如果您正在使用一个框架(类扩展帧),则不会得到


frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)

1
如果您正在使用Frame(类Extends Frame),则使用此.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - Jaimin Patel

1
如果您不扩展JFrame并在变量中使用JFrame本身,则可以使用:
frame.dispose();
System.exit(0);

0

this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

对我来说这个在类扩展帧的情况下有效


0
以下代码对我有效:
System.exit(home.EXIT_ON_CLOSE);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接