カルテ保存後ウインドウを閉じる(続)
以前 Exception が出て直していたのだが,頻度は減っていたもののやっぱり時々同じ Exception が出る。根本的に何かおかしいと思ってよく考えてみると,2つの問題点が分かった。編集終了後の EditorFrame を閉じるのは思ったより大変なことだった。
- まず,EditorFrame で KarteEditor が作られているのに,KarteEditor の方から EditorFrame.close() を呼んだらだめだろう。KarteEditor から EditorFrame.close() を呼んだら,戻ってきたら自分が既に消えていた,という事態になりうる。【2009/10/18追記】PropertyChangeListener の使い方を勉強して,KarteEditor で save が完了したら EditorFrame に PropertyChange を知らせて対処するように書き換えた。
- ChartMediator の調整も必要。ChartMediator は ChartImpl と EditorFrame で各々インスタンスが作られるが,KeyboardFocusManager にリスナが付くので,EditorFrame の Component をクリックした場合でも,ChartImpl と EditorFrame の両方の ChartMediator にイベントが行く仕様になっている。つまり,クリックされた Component は,ChartImpl からと,EditorFrame から,連続して2回 enter や exit を受け取る。
オリジナルの状態だと ChartImpl と EditorFrame の両方の実体があるので問題ないが,今回のように EditorFrame を先に閉じてしまうと,EditorFrame を閉じる際に発生したイベントが ChartImpl に伝わって,ChartImpl 側の ChartMediator から,もう無いはずの EditorFrame の Component に対して exit(getActions()) が送られて Exception が出る。
この過程でかかった微妙な時間により,それを受ける EditorFrame の実体がまだ残っていれば Exception は出ず,解放されてしまっていれば Null Pointer Exception が出る。Exception が毎回ではなく,たまに出ていたのはそういうわけだったようだ。
というわけで,EditorFrame.close() は EditorFrame 側で呼ぶように書き直し,ChartMediator は自分の component からのイベントのみ処理するようにした。
client/KarteEditor.java
SINGLE_MODE も使う場合は,save1 も同様に変更private void save2(final SaveParams params) throws DolphinException { ・ ・ // // 文書履歴の更新を通知する // chart.getDocumentHistory().getDocumentHistory(); ////↓セーブしたら,frame を閉じるようにする ← これはダメ // if (getContext() instanceof EditorFrame) chart.close(); ////↑ //// PropertyChangeListener で対応 boundSupport.firePropertyChange(KarteEditor.SAVE_DONE, false, true); } else { // errMsg を処理する // エラーを表示する JFrame parent = chart.getFrame(); String title = ClientContext.getString("karte.task.saveTitle"); JOptionPane.showMessageDialog(parent, errMsg, ClientContext.getFrameTitle(title), JOptionPane.WARNING_MESSAGE); } } }; // EditorFrame に save 後閉じる処理を入れたので,ここの Thread が終わらないうちに // EditorFrame が閉じてしまわないように,chart が EditorFrame の時は,仕事が終わるまで待ってもらう。 // if (chart instanceof EditorFrame) task.executeInForeground(); // else task.execute(); // PropertyChangeListener で対応 ////↑ task.execute(); }
helper/DBTask.java
////↓ /** * non thread version of execute * Thread を使わないで,Task が終了するまで待って欲しいとき用 * @return */ public T executeInForeground() { T ret = null; try { ret = doInBackground(); succeeded(ret); } catch (Exception ex) { System.out.println(ex); } return ret; } ////↑
client/EditorFrame.java
public void close() { if (mode == EditorMode.EDITOR) { if (editor.isDirty()) { ・ ・ switch (option) { case 0: editor.save(); //// editor が Dirty でなければ(セーブ完了していれば),EditorFrame を閉じる //// if (!editor.isDirty()) stop(); // PropertyChangeListener で対応 break; case 1: stop(); break; ・ ・
client/ChartMediator.java
class FocusPropertyChangeListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); logger.debug("focusManager propertyChange :" + prop); if ("focusOwner".equals(prop)) { // 自分の component からの propertyChange だけ処理するようにする Window w = ((KeyboardFocusManager) e.getSource()).getActiveWindow(); if ((w != null) && (w == chart.getFrame())) { Component comp = (Component) e.getNewValue(); if (comp instanceof JTextPane) { Object obj = ((JTextPane) comp).getClientProperty("kartePane"); if (obj != null && obj instanceof KartePane) { setCurKarteComposit((KarteComposite) obj); } } else if (comp instanceof KarteComposite) { setCurKarteComposit((KarteComposite) comp); } } } }
« マスタ検索画面の結果リストの文字色 | トップページ | ScheduledExecutorService の使い回し »
「OpenDolphin」カテゴリの記事
- Java 17 への移行(7) - OpenDolphin client の対応 (2023.02.04)
- Java 17 への移行(6) - Hibernate 6 でやらかす(2023.02.03)
- Java 17 への移行(5) - OpenDolphin server の対応(2023.02.02)
- Java 17 への移行(4) - OpenSearch の準備 [ubuntu 編](2023.02.01)
- Java 17 への移行(3) - OpenSearch の準備 [mac 編](2023.01.31)