を拡張する抽象クラスを持つアプリケーションがありますJDialog
。クラスを として、abstract void onClose()
クラスのコンストラクターに次のコードを追加します。
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
onClose();
}
}
イベントは期待どおりに発生しますが、奇妙なことが起こります。このクラスの具象拡張にメソッド内で new を作成するコードがあり、これJDialog
がである場合、操作を強制終了するまでイベントが継続的に発生します。onClose()
JDialog
defaultCloseOperation
JDialog.DISPOSE_ON_CLOSE
コードを次の SSCCE に分離しました。
// package removed
// imports removed
public class SSCCE extends JDialog {
public static void main(String[] args) {
SSCCE s = new SSCCE();
s.pack();
s.setVisible(true);
}
public SSCCE() {
setLayout(new GridLayout(1, 0, 0, 0));
JButton btn = new JButton("click me");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
System.out
.println("SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()");
onClose();
}
});
add(btn);
}
public void onClose() {
JDialog dialog = new JDialog();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
}
「クリックしてください」ボタンをクリックすると、空白JDialog
がSSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
表示され、コンソール ウィンドウに表示されます。空白のダイアログを閉じると、再び表示され、テキストが再び表示されます。
もう 1 つの非常に興味深い点は、初期化行を
JDialog dialog = new JDialog();
に
JDialog dialog = new JDialog() {
@Override
public synchronized void addWindowListener(WindowListener l) {
super.addWindowListener(l);
System.out
.println("SSCCE.onClose().new JDialog() {...}.addWindowListener()");
}
};
コンソールに次の出力が表示されます。
「クリックしてください」ボタンをクリックした場合:
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
ダイアログを最初に閉じるとき:
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
ダイアログを 2 回目に閉じると、次のようになります。
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
ダイアログを閉じるたびに、意図的に呼び出しているわけではありませんがaddWindowListener(WindowListener l)
、追加の時間が呼び出されます。
ダイアログに s を登録したくない のですが、単にメソッドをオーバーライドして呼び出しを行わないのは、ずさんすぎるWindowListener
と思います。addWindowListener(...)
super.addWindowListener(...)
Mac OS X 10.6.8 で Eclipse Indigo を使用して Java 1.6.0_31 を実行しています (問題がある場合は WindowBuilder を使用)。
誰にもアイデアはありますか?
ありがとう!