ホームページ目次前の話次の話

Javaのフォーカス要求はいつ処理されるのだろうか

2008年3月7日

Javaは、一度プログラムを書けば、異なるOSの上でも、そのまま動いてしまうという 素晴しい言語であり、Write once, run anywhere といううたい文句も用意されている。

はたしてそうであろうか?というより、Write once, run anywhere 自体、 もう死語になっているというのが現実ではないだろうか。

先日、Javaのプログラムをいじっていたら、キーボードの入力を受け付けなくなった。 要するに、キーフォーカスが目的のComponentになっていないのである。 JPanelでキー入力を処理したかっただけなのだが、 イベントがやってこないのではどうしようもない。

まったく駄目ではなく、ときどき、あるいはしばしばイベントが来なくなる。 IEだとかなりちゃんと動くのだが、Firefoxだと駄目になりやすかった。 また、機種依存問題に引っかかってしまったかと悪い予感がした。 さらに困ったことに、Eclipse上で動作確認しているとまったく発生しない。 Eclipse上でいくらテストしたって、実際の使用環境とは違う。 とくに、イベントのような、システム依存性が高いものは、 開発システム上でのテストは信用してはならない。

詳しく調べて行くと、 あるとき、溜まったキーイベントがまとめてやってくる。 まとめてやってこられても、入力と表示のタイミングが合わなくなって、 使えないGUIになってしまった訳だ。 お約束のように、トラブルはキー入力の周囲で発生する。

JPanelがフォーカスを取得するように、requestFocus() を使っていた。 フォーカスの問題で関係しそうなメソッドで最初に疑われるものである。 やむなく、正式のマニュアルを調べる。 すると、

このメソッドの動作はプラットフォームに依存しているため、 このメソッドを使用することは推奨されません。代わりに requestFocusInWindow() を使用することをお勧めします。

とあったので、requestFocusInWindow()に書換えてみた。 しかし、同様に不味い動作のままであった。 やむなく、しばし考えた。 マニュアルも、参考資料として挙げてある英文資料も検索機能をつかいながら 斜めに探した。

そして、また考えた。 requestしているだけであって、 いつ要求が実現されるかは神のみぞ知る世界である。 運が良ければ、直ぐに反応するだけである。

ということは、要求という甘ちょろい処理ではなく、 FocusEventを作って、そのイベントをpostすることにした。 システムのEventQueueに対して、直接イベントを投げ込んだ訳だ。

これで動かなかったらどうしてくれようと思ったが、 さすがにイベントを直接投げ付けたら、ちゃんと処理してくれた。

requestFocusInWindowなどで穏かに要求を出しても、 それが実際に処理されるには様々な条件があって、 そのうちの1つでも壊されると駄目なので、 何かが変になっているのであろう。 それをちゃんと見付けて直すのも1つのやり方だろうが、 requestは要求に過ぎないのだから、過大な期待をするのは止めて、 イベント直撃弾をかませることでバグ修正は終りにした。

久々にJavaのバグ修正に時間をかけてしまった。


ホームページ目次前の話次の話