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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/258099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:07:06  来源:igfitidea点击:

How to close a Java Swing application from the code

javaswing

提问by Hans-Peter St?rr

What is the proper way to terminate a Swing application from the code, and what are the pitfalls?

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

I'd tried to close my application automatically after a timer fires. But just calling dispose()on the JFramedidn't do the trick - the window vanished but the application did not terminate. However when closing the window with the close button, the application does terminate. What should I do?

我试图在计时器触发后自动关闭我的应用程序。但是,仅仅呼吁dispose()JFrame没有做的伎俩-窗口消失了,但应用程序并没有终止。但是,当使用关闭按钮关闭窗口时,应用程序会终止。我该怎么办?

采纳答案by James Schek

Your JFrame default close action can be set to "DISPOSE_ON_CLOSE" instead of EXIT_ON_CLOSE(why people keep using EXIT_ON_CLOSE is beyond me).

您的 JFrame 默认关闭操作可以设置为“ DISPOSE_ON_CLOSE”,而不是EXIT_ON_CLOSE(为什么人们一直使用 EXIT_ON_CLOSE 超出我的理解)。

If you have any undisposed windows or non-daemon threads, your application will not terminate. This should be considered a error (and solving it with System.exit is a very bad idea).

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

The most common culprits are java.util.Timer and a custom Thread you've created. Both should be set to daemon or must be explicitly killed.

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

If you want to check for all active frames, you can use Frame.getFrames(). If all Windows/Frames are disposed of, then use a debugger to check for any non-daemon threads that are still running.

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

回答by Daniel Spiewak

Try:

尝试:

System.exit(0);

Crude, but effective.

粗鲁,但有效。

回答by VonC

I guess a EXIT_ON_CLOSE

我猜是EXIT_ON_CLOSE

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

before System.exit(0)is better since you can write a Window Listenerto make some cleaning operations before actually leaving the app.

beforeSystem.exit(0)更好,因为您可以编写一个Window Listener在实际离开应用程序之前进行一些清理操作。

That window listener allows you to defined:

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

public void windowClosing(WindowEvent e) {
    displayMessage("WindowListener method called: windowClosing.");
    //A pause so user can see the message before
    //the window actually closes.
    ActionListener task = new ActionListener() {
        boolean alreadyDisposed = false;
        public void actionPerformed(ActionEvent e) {
            if (frame.isDisplayable()) {
                alreadyDisposed = true;
                frame.dispose();
            }
        }
    };
    Timer timer = new Timer(500, task); //fire every half second
    timer.setInitialDelay(2000);        //first delay 2 seconds
    timer.setRepeats(false);
    timer.start();
}

public void windowClosed(WindowEvent e) {
    //This will only be seen on standard output.
    displayMessage("WindowListener method called: windowClosed.");
}

回答by Vincent Ramdhanie

If I understand you correctly you want to close the application even if the user did not click on the close button. You will need to register WindowEvents maybe with addWindowListener() or enableEvents() whichever suits your needs better.

如果我理解正确,即使用户没有单击关闭按钮,您也想关闭应用程序。您可能需要使用 addWindowListener() 或 enableEvents() 注册 WindowEvents ,以更适合您的需求。

You can then invoke the event with a call to processWindowEvent(). Here is a sample code that will create a JFrame, wait 5 seconds and close the JFrame without user interaction.

然后,您可以通过调用 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();
    }

}

As you can see, the processWindowEvent() method causes the WindowClosed event to be fired where you have an oportunity to do some clean up code if you require before closing the application.

如您所见, processWindowEvent() 方法会触发 WindowClosed 事件,如果您需要在关闭应用程序之前有机会进行一些清理代码。

回答by Tamas Rev

I think, the idea is here the WindowListener - you can add any code there that you'd like to run before the thing shuts down

我认为,这个想法是 WindowListener - 你可以在那里添加任何你想在事情关闭之前运行的代码

回答by Eric Sadler

The following program includes code that will terminate a program lacking extraneous threads without explicitly calling System.exit(). In order to apply this example to applications using threads/listeners/timers/etc, one need only insert cleanup code requesting (and, if applicable, awaiting) their termination before the WindowEvent is manually initiated within actionPerformed().

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

For those who wish to copy/paste code capable of running exactly as shown, a slightly-ugly but otherwise irrelevant main method is included at the end.

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

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

回答by Kachwahed

May be the safe way is something like:

可能是安全的方式是这样的:

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

回答by JSideris

In response to other comments, DISPOSE_ON_CLOSE does not seem to properly exit the application - it only destroys the window, but the application will continue running. If you want to terminate the application use EXIT_ON_CLOSE.

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

回答by Reiner Lange

Take a look at the Oracle Documentation.

查看Oracle 文档

Starting from JDK 1.4 an Application terminates if:

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

  • There are no displayable AWT or Swing components.
  • There are no native events in the native event queue.
  • There are no AWT events in java EventQueues.
  • 没有可显示的 AWT 或 Swing 组件。
  • 本机事件队列中没有本机事件。
  • java EventQueues 中没有 AWT 事件。

Cornercases:

角箱:

The document states that some packages create displayable components without releasing them.A program which calls Toolkit.getDefaultToolkit() won't terminate.is among others given as an example.

该文档指出,某些包创建了可显示的组件而不释放它们。调用 Toolkit.getDefaultToolkit() 的程序不会终止。其中举个例子。

Also other Processes can keep AWT alive when they, for what ever reason, are sending events into the native event queue.

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

Also I noticed that on some Systems it takes a coupple of seconds before the Application actually terminates.

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