java Swing WindowListener 如何否决 JFrame 关闭
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3777146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can a Swing WindowListener veto JFrame closing
提问by Duncan McGregor
I have a frame, and want to prompt when the user closes it to save the document. But if they cancel, the frame shouldn't close.
我有一个框架,想在用户关闭它以保存文档时进行提示。但如果他们取消,框架不应该关闭。
frame.addWindowListener(new SaveOnCloseWindowListener(fileState));
...
public class SaveOnCloseWindowListener extends WindowAdapter {
private final FileState fileState;
public SaveOnCloseWindowListener(FileState fileState) {
this.fileState = fileState;
}
public void windowClosing(WindowEvent e) {
if (!fileState.onQuit())
cancelClose();
}
}
FileState looks at whether the document is dirty. If it isn't it does nothing and returns true. If it is dirty, it asks the user if he wants to save (YES/NO/CANCEL). If the user cancels at this point, it should abort the windowClosing.
FileState 查看文档是否脏。如果不是,则不执行任何操作并返回 true。如果它很脏,它会询问用户是否要保存(是/否/取消)。如果用户此时取消,则应中止 windowClosing。
All the suggestions I've seen on the net involve explicitly exiting in the windowClosing method, thus overriding the use of JFrame.setDefaultCloseOperation(), and duplicating the code in JFrame.processWindowEvent().
我在网上看到的所有建议都涉及在 windowClosing 方法中显式退出,从而覆盖 JFrame.setDefaultCloseOperation() 的使用,并复制 JFrame.processWindowEvent() 中的代码。
I actually have a dirty solution, but would like to see if there are any cleaner ones.
我实际上有一个肮脏的解决方案,但想看看是否有更清洁的解决方案。
Cheers
干杯
回答by Thirler
The right way is set JFrame.setDefaultCloseOperation
to DO_NOTHING_ON_CLOSE
when the window is created. And then just calling setVisible(false)
or dispose()
when your user accepts the close, or doing nothing when the close isn't accepted.
正确的方法是设置JFrame.setDefaultCloseOperation
到DO_NOTHING_ON_CLOSE
创建窗口时。然后只是调用setVisible(false)
或dispose()
当您的用户接受关闭时,或者在不接受关闭时什么都不做。
The whole purpose of JFrame.setDefaultCloseOperation
is only to prevent the need to implement WindowListeners
for the most simple actions. The actions performed by these default close operations are very simple.
整个目的JFrame.setDefaultCloseOperation
只是为了防止需要执行WindowListeners
最简单的操作。这些默认关闭操作执行的操作非常简单。
EDIT:
编辑:
I've added the solution I'm describing. This assumes you want the frame to be fully deleted.
我已经添加了我正在描述的解决方案。这假设您希望完全删除框架。
frame.setDefaultCloseOperation(setDefaultCloseOperation);
frame.addWindowListener(new SaveOnCloseWindowListener(fileState));
...
public class SaveOnCloseWindowListener extends WindowAdapter {
private final FileState fileState;
public SaveOnCloseWindowListener(FileState fileState) {
this.fileState = fileState;
}
public void windowClosing(WindowEvent e) {
if (fileState.onQuit())
frame.dispose();
}
}
回答by camickr
Closing an Applicationmight make the process a little easier for you.
关闭应用程序可能会使您的过程更轻松一些。
回答by Duncan McGregor
Thanks to the input from Thirler and camickr. This is my solution, which I'm sure that some will hate, but avoids duplicating logic in JFrame, and allows client code to setDefaultCloseOperation as usual.
感谢来自 Thirler 和 camickr 的输入。这是我的解决方案,我相信有些人会讨厌它,但避免在 JFrame 中复制逻辑,并允许客户端代码像往常一样 setDefaultCloseOperation。
class MyFrame {
@Override protected void processWindowEvent(WindowEvent e) {
try {
super.processWindowEvent(e);
} catch (SaveOnCloseWindowListener.VetoException x) {}
}
}
public class SaveOnCloseWindowListener extends WindowAdapter {
public static class VetoException extends RuntimeException {
}
private final DocumentController documentController;
public SaveOnCloseWindowListener(DocumentController documentController) {
this.documentController = documentController;
}
public void windowClosing(WindowEvent e) {
if (!documentController.onClose())
throw new VetoException();
}
}
回答by Duncan McGregor
I think that this is the logical expression of Thirler's answer, and kind of what I was trying to avoid.
我认为这是 Thirler 回答的合乎逻辑的表达,也是我试图避免的。
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new SaveOnCloseWindowListener(fileState, JFrame.EXIT_ON_CLOSE));
public class SaveOnCloseWindowListener extends WindowAdapter {
private final int closeOperation;
private final Document document;
public SaveOnCloseWindowListener(int closeOperation, Document document) {
this.closeOperation = closeOperation;
this.document = document;
}
public void windowClosing(WindowEvent e) {
if (!document.onClose())
doClose((Window) e.getSource());
}
private void doClose(Window w) {
switch (closeOperation) {
case JFrame.HIDE_ON_CLOSE:
w.setVisible(false);
break;
case JFrame.DISPOSE_ON_CLOSE:
w.dispose();
break;
case JFrame.DO_NOTHING_ON_CLOSE:
default:
break;
case JFrame.EXIT_ON_CLOSE:
System.exit(0);
break;
}
}
}