Как правильно действовать при закрытии окон в Java/ Swing?
Я только что написал этот тестовый код в своем классе CustomUIPanel:
public static void main(String[] args) {
final JDialog dialog = CustomUIPanel.createDialog(null,
CustomUIPanel.selectFile());
dialog.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
Работает правильно если CustomUIPanel.main()
является точкой входа в программу, но это заставляет меня задуматься: что если другой класс называется CustomUIPanel.main()
для тестирования? Тогда мой звонок System.exit(0)
это неверно.
Есть ли способ указать потоку отправки события Swing автоматически завершиться, если нет окон верхнего уровня?
Если нет, то что правильно делать JDialog/JFrame при закрытии, если целью является выход из программы при закрытии всех окон верхнего уровня?
6 ответов
Вы можете использовать setDefaultCloseOperation()
метод JDialog
, указав DISPOSE_ON_CLOSE
:
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
Смотрите также 12.8 Выход из программы.
Приложение: Включая полезный ответ @camickr, этот пример завершается, когда окно закрыто или нажата кнопка закрытия.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
/** @see http://stackru.com/questions/5540354 */
public class DialogClose extends JDialog {
public DialogClose() {
this.setLayout(new GridLayout(0, 1));
this.add(new JLabel("Dialog close test.", JLabel.CENTER));
this.add(new JButton(new AbstractAction("Close") {
@Override
public void actionPerformed(ActionEvent e) {
DialogClose.this.setVisible(false);
DialogClose.this.dispatchEvent(new WindowEvent(
DialogClose.this, WindowEvent.WINDOW_CLOSING));
}
}));
}
private void display() {
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new DialogClose().display();
}
});
}
}
Не уверен насчет использования JDialog.
Но при использовании JFrame вы должны использовать frame.dispose(). Если кадр является последним открытым кадром, то VM выйдет.
Обратите внимание, что в диалоге нет опции EXIT_ON_CLOSE, так как он обычно не должен выходить из ВМ.
При закрытии диалога вы всегда можете получить родительский фрейм диалогов. Затем вы можете отправить событие в кадр, чтобы сказать ему закрыть себя. Что-то вроде:
WindowEvent windowClosing = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
//Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(windowClosing);
frame.dispatchEvent(windowClosing);
Вот что я бы порекомендовал: dialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Что ж,
Вместо этого вы можете использовать JFrame. Предполагается, что JDialog будет использоваться как всплывающее окно приложения, которое выполняется в JFrame, чтобы привлечь внимание пользователей и приостановить основное приложение. Если JFrame закрыт, вы можете вызвать System.exit(0)
Диалог имеет getParent()
метод, который, я думаю, установлен в ноль в вашем случае здесь CustomUIPanel.createDialog(null,
Вы можете использовать это, чтобы выйти условно.