Какое правильное действие следует предпринять при закрытии окон в 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 Выход Из Программы.

Addendum: включая полезный ответ @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://stackoverflow.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.распоряжаться.)( Если кадр является последним открытым кадром, то VM выйдет.

Примечание. диалог не имеет опции EXIT_ON_CLOSE, так как он обычно не должен выходить из виртуальной машины.

при закрытии диалога вы всегда можете получить Родительский фрейм диалогов. Затем вы можете отправить событие в кадр, чтобы сказать ему закрыть себя. Что-то вроде:

WindowEvent windowClosing = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
//Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(windowClosing);
frame.dispatchEvent(windowClosing);

использовать

this.dispose();

это должно работать.


Ну

вместо этого вы можете использовать JFrame. JDialog предполагается использовать как всплывающее окно приложения, которое работает в JFrame, чтобы привлечь внимание пользователей и приостановить основное приложение. Если JFrame закрыт, Вы можете вызвать System.выход(0)


в диалоговом окне getParent() метод, который я предполагаю, имеет значение null в вашем случае здесь CustomUIPanel.createDialog(null,

вы можете использовать это, чтобы выйти условно.


вот что я бы порекомендовал : dialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);