Answers:
您可以将JFrame的默认关闭操作设置为“ DISPOSE_ON_CLOSE
”,而不是EXIT_ON_CLOSE
(为什么人们继续使用EXIT_ON_CLOSE不在我的视野之内)。
如果您有未处理的Windows窗口或非守护线程,则您的应用程序不会终止。这应该被认为是一个错误(使用System.exit解决它是一个非常糟糕的主意)。
最常见的罪魁祸首是java.util.Timer和您创建的自定义线程。两者都应设置为守护程序,或者必须将其显式杀死。
如果要检查所有活动帧,可以使用Frame.getFrames()
。如果所有Windows /框架都已废弃,请使用调试器检查是否仍在运行任何非守护线程。
back
窗口,该怎么办?如果第二个窗口,然后关闭并使用DISPOSE_ON_CLOSE
该程序不会终止,因为第一个窗口仍然是“未予处置” ...有没有解决这个办法没有用DISPOSE_ON_CLOSE
?
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
before 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();
}
});
Frame
用大写字母命名变量的方式非常糟糕,就像类的名称一样……
以下程序包括一些代码,这些代码将在没有显式调用System.exit()的情况下终止缺少外部线程的程序。为了将此示例应用于使用线程/侦听器/计时器/等的应用程序,只需在actionPerformed()中手动启动WindowEvent之前,插入插入清理代码即可请求(并在可能的情况下等待)其终止。
对于那些希望能够复制/粘贴能够完全按照所示方式运行的代码的人,最后包括一个有点丑陋但不相关的main方法。
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);
}
});
}
}
如果我对您的理解正确,即使用户没有单击关闭按钮,也要关闭该应用程序。您可能需要使用更适合您的需要的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事件。
看一下Oracle文档。
从JDK 1.4开始,如果满足以下条件,则应用程序终止:
角箱:
该文档指出,某些软件包会创建可显示的组件而不释放它们。调用Toolkit.getDefaultToolkit()的程序不会终止。以其他示例为例。
当其他进程出于某种原因将事件发送到本机事件队列中时,它们也可以使AWT保持活动状态。
我还注意到,在某些系统上,应用程序实际终止需要花费几秒钟的时间。