Как закрыть приложение Java Swing из кода
Как правильно завершить приложение Swing из кода, и каковы подводные камни?
Я попытался закрыть приложение автоматически после срабатывания таймера. Но просто звоню dispose()
на JFrame
не сделал трюк-окно исчезло, но приложение не завершилось. Однако при закрытии окна с помощью кнопки закрыть приложение завершается. Что же мне делать?
9 ответов:
ваше действие закрытия JFrame по умолчанию может быть установлено в "
DISPOSE_ON_CLOSE
" вместоEXIT_ON_CLOSE
(почему люди продолжают использовать EXIT_ON_CLOSE вне меня).Если у вас есть какие-либо нераскрытые окна или не-демон потоки, ваше приложение не завершится. Это следует считать ошибкой (и решать ее с помощью системы.выход-это очень плохая идея).
наиболее распространенными виновниками являются java.утиль.Таймер и пользовательский поток, который вы создали. Оба должны быть установлены в daemon или должны быть явно убитый.
Если вы хотите проверить все активные кадры, вы можете использовать
Frame.getFrames()
. Если все окна/фреймы удалены, то используйте отладчик для проверки всех не-демонических потоков, которые все еще работают.
Я думаю, a EXIT_ON_CLOSE
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
до
System.exit(0)
лучше, так как можно написать Слушателя Окна чтобы сделать некоторые операции очистки перед фактическим выходом из приложения.это окно прослушивателя позволяет определить:
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."); }
может быть безопасным способом является что-то вроде:
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(); } });
следующая программа включает в себя код, который завершит программу, не имеющую посторонних потоков без явного вызова системы.выход.)( Чтобы применить этот пример к приложениям, использующим потоки / прослушиватели / таймеры/и т. д., Нужно только вставить код очистки, запрашивающий (и, если применимо, ожидающий) их завершение, прежде чем WindowEvent будет вручную инициирован в actionPerformed().
для тех, кто хочет скопировать / вставить код, способный работать точно так, как показано, a слегка уродливый, но в остальном неуместный основной метод включен в конце.
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); } }); } }
Если я правильно понял вы хотите закрыть приложение, даже если пользователь не нажал на кнопку "Закрыть". Вам нужно будет зарегистрировать WindowEvents, возможно, с addWindowListener() или enableEvents () в зависимости от ваших потребностей лучше.
затем можно вызвать событие с помощью вызова 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 приложение завершается, если:
- нет никаких отображаемых компонентов AWT или Swing.
- в очереди собственных событий нет собственных событий.
- в Java EventQueues нет событий AWT.
Cornercases:
в документе указано, что некоторые пакеты создают отображаемые компоненты без освобождения их.программа, которая вызывает инструментарий.getDefaultToolkit () не завершается. среди прочих приводится в качестве примера.
также другие процессы могут поддерживать AWT, когда они, по какой-либо причине, отправляют события в собственную очередь событий.
также я заметил, что на некоторых системах требуется несколько секунд, прежде чем приложение фактически завершится.