How can a Swing WindowListener veto JFrame closing

后端 未结 4 1048
北恋
北恋 2020-11-30 14:03

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          


        
相关标签:
4条回答
  • 2020-11-30 14:27

    Closing an Application might make the process a little easier for you.

    0 讨论(0)
  • 2020-11-30 14:27

    I think that this is the logical expression of Thirler's answer, and kind of what I was trying to avoid.

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 14:34

    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.

    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.

    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();
        }
    }
    
    0 讨论(0)
  • 2020-11-30 14:39

    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.

    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();
        }
    }
    
    0 讨论(0)
提交回复
热议问题