如何从代码中关闭Java Swing应用程序

时间:2008-11-03 08:01:54

标签: java swing

从代码中终止Swing应用程序的正确方法是什么,有哪些陷阱?

我试图在计时器触发后自动关闭我的应用程序。但是只是在dispose()上调用JFrame没有做到这一点 - 窗口消失但应用程序没有终止。但是,当使用关闭按钮关闭窗口时,应用程序会终止。我该怎么办?

9 个答案:

答案 0 :(得分:102)

您的JFrame默认关闭操作可以设置为“DISPOSE_ON_CLOSE”而不是EXIT_ON_CLOSE(为什么人们继续使用EXIT_ON_CLOSE超出我的范围。)

如果您有任何未曝光的窗口或非守护程序线程,您的应用程序将不会终止。这应该被认为是一个错误(使用System.exit解决它是一个非常糟糕的主意)。

最常见的罪魁祸首是java.util.Timer和您创建的自定义线程。两者都应该设置为守护进程或必须被明确杀死。

如果要检查所有活动帧,可以使用Frame.getFrames()。如果处理掉所有Windows / Frame,则使用调试器检查仍在运行的任何非守护程序线程。

答案 1 :(得分:34)

我猜是EXIT_ON_CLOSE

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

之前的

更好,因为您可以在实际离开应用之前编写Window Listener来进行一些清理操作。

该窗口监听器允许您定义:

System.exit(0)

答案 2 :(得分:15)

尝试:

System.exit(0);

原油,但有效。

答案 3 :(得分:11)

可能是安全的方式:

    private JButton btnExit;
    ...
    btnExit = new JButton("Quit");      
    btnExit.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e){
            Container frame = btnExit.getParent();
            do 
                frame = frame.getParent(); 
            while (!(frame instanceof JFrame));                                      
            ((JFrame) frame).dispose();
        }
    });

答案 4 :(得分:9)

以下程序包含将在没有显式调用System.exit()的情况下终止缺少无关线程的程序的代码。为了将此示例应用于使用线程/侦听器/定时器/等的应用程序,在actionPerformed()中手动启动WindowEvent之前,只需要插入清除代码请求(以及,如果适用,等待)它们的终止。

对于那些希望复制/粘贴能够完全按照所示方式运行的代码的人,最后会包含一个稍微丑陋但不相关的主要方法。

public class CloseExample extends JFrame implements ActionListener {

    private JButton turnOffButton;

    private void addStuff() {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        turnOffButton = new JButton("Exit");
        turnOffButton.addActionListener(this);
        this.add(turnOffButton);
    }

    public void actionPerformed(ActionEvent quitEvent) {
        /* Iterate through and close all timers, threads, etc here */
        this.processWindowEvent(
                new WindowEvent(
                      this, WindowEvent.WINDOW_CLOSING));
    }

    public CloseExample() {
        super("Close Me!");
        addStuff();
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                CloseExample cTW = new CloseExample();
                cTW.setSize(200, 100);
                cTW.setLocation(300,300);
                cTW.setVisible(true);
            }
        });
    }
}

答案 5 :(得分:4)

如果我理解正确,即使用户没有点击关闭按钮,也要关闭应用程序。您需要使用addWindowListener()或enableEvents()注册WindowEvents,以便更好地满足您的需求。

然后,您可以通过调用processWindowEvent()来调用该事件。下面是一个示例代码,它将创建一个JFrame,等待5秒并在没有用户交互的情况下关闭JFrame。

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

public class ClosingFrame extends JFrame implements WindowListener{

public ClosingFrame(){
    super("A Frame");
    setSize(400, 400);
            //in case the user closes the window
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
            //enables Window Events on this Component
            this.addWindowListener(this);

            //start a timer
    Thread t = new Timer();
            t.start();
    }

public void windowOpened(WindowEvent e){}
public void windowClosing(WindowEvent e){}

    //the event that we are interested in
public void windowClosed(WindowEvent e){
    System.exit(0);
}

public void windowIconified(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowActivated(WindowEvent e){}
public void windowDeactivated(WindowEvent e){}

    //a simple timer 
    class Timer extends Thread{
           int time = 10;
           public void run(){
     while(time-- > 0){
       System.out.println("Still Waiting:" + time);
               try{
                 sleep(500);                     
               }catch(InterruptedException e){}
             }
             System.out.println("About to close");
    //close the frame
            ClosingFrame.this.processWindowEvent(
                 new WindowEvent(
                       ClosingFrame.this, WindowEvent.WINDOW_CLOSED));
           }
    }

    //instantiate the Frame
public static void main(String args[]){
          new ClosingFrame();
    }

}

正如您所看到的,processWindowEvent()方法会导致触发WindowClosed事件,如果您在关闭应用程序之前需要执行某些清理代码,则会触发该事件。

答案 6 :(得分:2)

查看Oracle Documentation

从JDK 1.4开始,如果出现以下情况,应用程序将终止:

  • 没有可显示的AWT或Swing组件。
  • 原生事件队列中没有本机事件。
  • java EventQueues中没有AWT事件。

Cornercases:

该文档声明某些包创建可显示的组件而不释放它们。A program which calls Toolkit.getDefaultToolkit() won't terminate.是作为示例提供的。

当其他原因将其发送到本机事件队列时,其他进程也可以保持AWT处于活动状态。

此外,我注意到在某些系统上,在应用程序实际终止之前需要几秒钟的时间。

答案 7 :(得分:0)

我认为,这个想法就在这里WindowListener - 您可以在事物关闭之前添加任何您想要运行的代码

答案 8 :(得分:0)

作为对其他评论的回应,DISPOSE_ON_CLOSE似乎没有正确退出应用程序 - 它只会破坏窗口,但应用程序将继续运行。如果要终止应用程序,请使用EXIT_ON_CLOSE。