カルテ保存後ウインドウを閉じる(続)
以前 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」カテゴリの記事
- 運用18年目のまとめ(2026.02.07)
- IME on/off の切換 - その5(2026.01.05)
- IME on/off の切換 - その4(2025.12.23)
- IME on/off の切換 - その3(2025.12.20)
- OpenDolphin: Java 25 / WildFly 38 への移行(2025.11.09)


