Как Swing WindowListener может наложить вето на JFrame? - PullRequest
8 голосов
/ 23 сентября 2010

У меня есть фрейм, и я хочу запросить, когда пользователь закроет его, чтобы сохранить документ.Но если они отменяются, кадр не должен закрываться.

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.

Все предложения, которые я видел в сети, включают явный выход из метода windowClosing, таким образом, переопределяя использование JFrame.setDefaultCloseOperation (), идублирование кода в JFrame.processWindowEvent ().

У меня действительно есть грязный раствор, но я хотел бы посмотреть, есть ли более чистые.

Приветствия

Ответы [ 4 ]

15 голосов
/ 23 сентября 2010

Правильный путь устанавливается JFrame.setDefaultCloseOperation на DO_NOTHING_ON_CLOSE при создании окна. А затем просто звоните setVisible(false) или dispose(), когда ваш пользователь принимает закрытие, или ничего не делаете, когда закрытие не принимается.

Вся цель JFrame.setDefaultCloseOperation состоит только в том, чтобы предотвратить необходимость реализации WindowListeners для самых простых действий. Действия, выполняемые этими операциями закрытия по умолчанию, очень просты.

EDIT:

Я добавил решение, которое описываю. Это предполагает, что вы хотите, чтобы кадр был полностью удален.

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();
    }
}
1 голос
/ 23 сентября 2010

Закрытие приложения может немного облегчить вам процесс.

0 голосов
/ 24 сентября 2010

Благодаря вкладу Тирлера и Камикра. Это мое решение, которое, я уверен, некоторые будут ненавидеть, но избегает дублирования логики в 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();
    }
}
0 голосов
/ 23 сентября 2010

Я думаю, что это логическое выражение ответа Тирлера и то, чего я пытался избежать.

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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...