TITLE:JFrameの終了をキャンセル

JFrameの終了をキャンセル

編集者:Terai Atsuhiro
作成日:2004-08-09
更新日:2024-02-15 (木) 20:17:21

概要

JFrameを閉じる前に、本当に終了してよいかや、終了をキャンセルするかどうかなどを確認するダイアログを表示します。

#screenshot

サンプルコード

public static final String TITLE_CHANGE = "hogehoge";
private final JTextArea textarea = new JTextArea();
private final JButton initButton = new JButton("保存");
private final JFrame frame;
public MainPanel(final JFrame frame) {
  super(new BorderLayout());
  this.frame = frame;
  final String title = frame.getTitle();
  addPropertyChangeListener(new PropertyChangeListener() {
    public void propertyChange(PropertyChangeEvent evt) {
      if(TITLE_CHANGE.equals(evt.getPropertyName())) {
        Boolean flg = (Boolean)evt.getNewValue();
        System.out.println(""+flg.toString());
        if(flg.booleanValue()) {
          frame.setTitle(title+"- [変更]");
        }else{
          frame.setTitle(title);
        }
      }
    }
  });
  frame.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
      if(!title.equals(frame.getTitle())) {
        java.awt.Toolkit.getDefaultToolkit().beep();
        String[] obj = {"テストテキストは変更されています。",
                        "終了する前に保存しますか?"};
        int retValue = JOptionPane.showConfirmDialog(frame, obj,
                        "テストアプリ",
                        JOptionPane.YES_NO_CANCEL_OPTION);
        if(retValue==JOptionPane.YES_OPTION) {
          //保存が成功した場合と失敗した場合
          //boolean ret = save();
          //if(ret) {
          //保存が成功したので終了
          //  frame.setDefaultCloseOperation(
          //        WindowConstants.EXIT_ON_CLOSE);
          //}else{
          //保存に失敗したのでエラーを出してもとに戻る
          //  frame.setDefaultCloseOperation(
          //        WindowConstants.DO_NOTHING_ON_CLOSE);
          //  return;
          //}
          System.out.println("本当はちゃんと保存して終了");
          frame.setDefaultCloseOperation(
                     WindowConstants.EXIT_ON_CLOSE);
        }else if(retValue==JOptionPane.NO_OPTION) {
          System.out.println("保存しないで終了");
          frame.setDefaultCloseOperation(
                     WindowConstants.EXIT_ON_CLOSE);
        }else if(retValue==JOptionPane.CANCEL_OPTION) {
          System.out.println("終了をキャンセル");
          frame.setDefaultCloseOperation(
                     WindowConstants.DO_NOTHING_ON_CLOSE);
        }
      }else{
        System.out.println("変更されていないのでそのまま終了");
        frame.setDefaultCloseOperation(
                     WindowConstants.EXIT_ON_CLOSE);
      }
    }
  });
  textarea.setText("テスト");
  textarea.getDocument().addDocumentListener(new DocumentListener() {
    public void insertUpdate(DocumentEvent e) {
      initButton.setEnabled(true);
      MainPanel.this.firePropertyChange(TITLE_CHANGE, Boolean.FALSE,
                                                      Boolean.TRUE);
    }
    public void removeUpdate(DocumentEvent e) {
      initButton.setEnabled(true);
      MainPanel.this.firePropertyChange(TITLE_CHANGE, Boolean.FALSE,
                                                      Boolean.TRUE);
    }
    public void changedUpdate(DocumentEvent e) {}
  });
  initButton.setEnabled(false);
  initButton.addActionListener(new AbstractAction("保存") {
    public void actionPerformed(ActionEvent ae) {
      System.out.println("本当はちゃんと保存すること");
      MainPanel.this.firePropertyChange(TITLE_CHANGE, Boolean.TRUE,
                                                      Boolean.FALSE);
      initButton.setEnabled(false);
    }
  });
  add(textarea, BorderLayout.CENTER);
  add(initButton, BorderLayout.SOUTH);
  setPreferredSize(new Dimension(512, 320));
}
  • &jnlp;
  • &jar;
  • &zip;

解説

上記のサンプルでは、JFrameを閉じるようとしたときに、内部のテキストが変更されている場合は、「終了する前に保存しますか?」と確認ダイアログを表示するようになっています。

  • はい
    • 実際に使用する場合は、ここで変更されたテキストを保存するような処理を実装します。
    • 上記のサンプルではなにもしないで、WindowConstants.EXIT_ON_CLOSE を JFrame#setDefaultCloseOperation(int)メソッドで設定して、JFrameを終了しています。
  • いいえ
    • WindowConstants.EXIT_ON_CLOSE を JFrame#setDefaultCloseOperation(int)メソッドで設定して、JFrameを終了しています。
  • 取り消し
    • WindowConstants.DO_NOTHING_ON_CLOSE を JFrame#setDefaultCloseOperation(int)メソッドで設定して、終了をキャンセルしています。

テキストが変更されているかどうかは、タイトルの文字列をフラグにして判断できるようになっています。

  • ドキュメントに文字列が追加されたとき、ソース側からfirePropertyChangeなどで、リスナーに変更をイベントで報告
  • リスナー側ではこのイベントを受け、JFrameのタイトルを変更

コメント

  • 私は以前 この終了をキャンセルするかどうかなどを確認するダイアログを作成したことがあります。あなたのソースコードは 参考のかいがあると思います。でも ひとつの問題があるんですけど、textareaに入力した文字列を削除する場合は JFrameのタイトルが変化されていません、どうですか? -- そうがい