代码之家  ›  专栏  ›  技术社区  ›  Duncan McGregor Evgeniy Dorofeev

Swing WindowListener如何阻止JFrame关闭

  •  8
  • Duncan McGregor Evgeniy Dorofeev  · 技术社区  · 14 年前

    我有一个框架,想在用户关闭它以保存文档时提示。但是如果取消,框架就不应该关闭。

    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查看文档是否脏。如果不是,它什么也不做,然后返回真。如果是脏的,它会询问用户是否要保存(是/否/取消)。如果用户此时取消,则应中止关闭窗口。

    我在网上看到的所有建议都涉及显式退出WindowClosing方法,从而覆盖jframe.setDefaultCloseOperation()的使用,并复制jframe.processWindowEvent()中的代码。

    我实际上有一个肮脏的解决方案,但想看看有没有更干净的。

    干杯

    4 回复  |  直到 14 年前
        1
  •  15
  •   Thirler    14 年前

    正确的方法已经确定了 JFrame.setDefaultCloseOperation DO_NOTHING_ON_CLOSE 创建窗口时。然后打电话 setVisible(false) dispose() 当您的用户接受关闭时,或者在关闭未被接受时不执行任何操作。

    的全部目的 jframe.setDefaultCloseOperation(关闭操作) 只是为了防止需要实施 WindowListeners 最简单的动作。这些默认关闭操作执行的操作非常简单。

    编辑:

    我已经添加了我描述的解决方案。这假定您希望完全删除框架。

    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();
        }
    }
    
        2
  •  1
  •   camickr    14 年前

    Closing an Application 可能会使过程对您来说更简单一些。

        3
  •  0
  •   Duncan McGregor Evgeniy Dorofeev    14 年前

    我认为这是第三者答案的逻辑表达,也是我试图避免的。

    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;
            }
        }
    }
    
        4
  •  0
  •   Duncan McGregor Evgeniy Dorofeev    14 年前

    多亏了蒂勒和卡米克的投入。这是我的解决方案,我确信有些人会讨厌它,但是避免了在JFrame中复制逻辑,并且允许客户机代码像往常一样设置默认关闭操作。

    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();
        }
    }