如何从代码中closuresJava Swing应用程序

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

在计时器触发后,我试图自动closures应用程序。 但只是调用JFrame上的dispose()并没有办法 – 窗口消失了,但应用程序没有终止。 但是,使用closuresbuttonclosures窗口时,应用程序会终止。 我该怎么办?

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

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

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

如果你想检查所有活动的框架,你可以使用Frame.getFrames() 。 如果所有的Windows / Frame都被丢弃,那么使用一个debugging器来检查是否有任何仍在运行的非守护进程线程。

我想一个EXIT_ON_CLOSE

 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

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

那个窗口监听器允许你定义:

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

尝试:

 System.exit(0); 

原油,但有效。

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

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

下面的程序包含的代码将会终止一个程序缺乏多余的线程,而不显式调用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); } }); } } 

如果我理解正确,即使用户没有单击closuresbutton,也要closures该应用程序。 您需要注册WindowEvents,也许使用addWindowListener()或enableEvents()来更好的满足您的需求。

然后可以调用processWindowEvent()来调用事件。 这里是一个示例代码,它将创build一个JFrame,等待5秒钟,然后closuresJFrame而无需用户交互。

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

正如你所看到的,如果你需要closures应用程序,processWindowEvent()方法会导致WindowClosed事件被激发,如果你需要的话,你可以使用oportunity做一些清理代码。

看看Oracle文档 。

从JDK 1.4开始,应用程序在以下情况下终止:

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

Cornercases:

该文件指出,一些包创build可显示的组件,而不释放它们。 调用Toolkit.getDefaultToolkit()的程序不会终止。 除此之外作为一个例子。

另外其他进程可以保持AWT活着,当他们由于某种原因将事件发送到本地事件队列。

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

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

为了响应其他评论,DISPOSE_ON_CLOSE似乎不能正确退出应用程序 – 它只会破坏窗口,但应用程序将继续运行。 如果您想终止应用程序,请使用EXIT_ON_CLOSE。