在java/swing中关闭窗口时,正确的操作是什么?

在java/swing中关闭窗口时,正确的操作是什么?,java,swing,dialog,Java,Swing,Dialog,我刚刚在CustomUIPanel类中编写了以下测试代码: public static void main(String[] args) { final JDialog dialog = CustomUIPanel.createDialog(null, CustomUIPanel.selectFile()); dialog.addWindowListener(new WindowAdapter() { @Override public void w

我刚刚在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()
进行测试会怎么样?然后我对
系统的调用。退出(0)
不正确

如果没有顶级窗口,是否有方法告诉Swing事件调度线程自动退出

如果不是,如果目标是在所有顶层窗口关闭时退出程序,那么JDialog/JFrame在关闭时应该做什么

您可以使用JFrame来代替。JDialog应该用作在JFrame中运行的应用程序的弹出窗口,以吸引用户的注意并暂停主应用程序。
如果JFrame关闭,您可以调用System.exit(0)

对话框有一个
getParent()
方法,我猜在这里的例子中,该方法被设置为null
CustomUIPanel.createDialog(null,


您可以使用它有条件地退出。

不确定何时使用JDialog

但是当使用JFrame时,应该使用frame.dispose()。如果该帧是最后一个打开的帧,则VM将退出

注意:对话框没有EXIT_ON_CLOSE选项,因为它通常不应该退出VM

关闭对话框时,您始终可以获得对话框的父帧。然后,您可以向该帧发送一个事件,告诉它自己关闭。类似于:

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

以下是我的建议:
dialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
您可以使用
JDialog
的方法,指定
DISPOSE_ON_CLOSE

setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
另见

附录:结合@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();
            }
        });
    }
}
使用


它应该可以工作。

这会在运行时抛出
java.lang.IllegalArgumentException
。VM可能会退出,也可能不会退出,这取决于创建该框架的代码。+1这也适用于单独关闭对话框本身。@Ingo,实际上这并不依赖于创建该框架的代码。它绕过了setDefaultCloseOperation(…)并且直接处理。@camickr:你的意思是在主窗口关闭后不可能执行某些操作?@Ingo,我不知道你在问什么。如果处理最后一帧,VM将退出。但是如果我有两个或三个独立运行的JFrames,则
System.exit()
是一个不合适的操作。是的,那么您应该设置默认的关闭操作。啊哈!您是正确的,这里的关键文档是“注意:当Java虚拟机(VM)中的最后一个可显示窗口被释放时,VM可能会终止。”()我从未意识到这是处理窗口的一个有用的副作用。+1,我知道最后一帧上的dispose()将退出VM。现在确认最后一个对话框上的dispose()也将退出VM。否。请阅读“VM可能会终止”(也就是说,如果GUI和GUI工作线程的创建是主线程中的最后一个操作,那么不可否认,通常情况就是这样)@Ingo:我认为上面提到的可能的警告是指。当最后一个顶级容器关闭时,事件队列线程终止,但是守护进程线程或未捕获的EDT异常可能会阻碍干净的退出。我怀疑@camickr意味着在正常的事件过程中退出。@trashgod-当然,我想指出的是GUI线程只是读取,而GUI对象只是对象。虚拟机中没有魔法会导致它仅仅因为GUI线程终止而终止。可能还有其他活动线程尚未终止,也没有守护进程线程。这对我来说很有效。我有一个程序,使用JDialog查询密码。获得密码后,进程继续进行正在运行,即使
dialog.setDefaultCloseOperation(JFrame.DISPOSE\u ON\u CLOSE)
并且主操作已经完成。在密码检索之后添加
DISPOSE
,最终成功结束该过程。
this.dispose();