キーバインディングに関する明確なチュートリアルを数回読んだことがありますが、私の脳のキャッシュは複雑なプロセスを保持するのに十分な大きさではないようです。
私はキーバインディングの問題をデバッグしていました(間違った条件を使用していたことが判明しました)、そして(残念ながら)匿名のJavaエンジニアによってJComponent.WHEN_*プライベートなパッケージの簡潔で陽気なjavadocに出くわしました。javax.swing.KeyboardManager
KeyEventDispatcher私の質問はこれです:最初にチェックされているものを除いて、説明は何かを見逃したり、間違えたりしますか?
KeyboardManagerクラスは、WHEN_IN_FOCUSED_WINDOWスタイルのアクションのキーボードアクションをディスパッチするために使用されます。他の条件のアクションは、JComponentで直接処理されます。
これは、私が理解しているように、キーボードディスパッチが少なくとも[原文のまま]どのように機能するかについてのシマンティクス[原文のまま]の説明です。
KeyEventsは、フォーカスされたコンポーネントにディスパッチされます。フォーカスマネージャーは、このイベントの処理で最初のクラックを取得します。フォーカスマネージャーがそれを望まない場合、JComponentはsuper.processKeyEvent()を呼び出します。これにより、リスナーはイベントを処理する機会が与えられます。
リスナーの誰もがイベントを「消費」しない場合、キーバインディングはショットを取得します。これは物事が面白くなり始めるところです。まず、WHEN_FOCUSED条件で定義されたKeyStokes[原文のまま]がチャンスを得ます。これらのいずれもイベントを必要としない場合、コンポーネントは、親がタイプWHEN_ANCESTOR_OF_FOCUSED_COMPONENTのアクションを探しているにもかかわらずウォークします。
まだ誰もそれを持っていない場合、それはここに行き着きます。次に、WHEN_IN_FOCUSED_WINDOWイベントに登録されているコンポーネントを探し、それらを起動します。それらのどれも見つからない場合は、イベントをメニューバーに渡し、それらにクラックを持たせることに注意してください。それらは異なる方法で処理されます。
最後に、内部フレームを見ているかどうかを確認します。私たちがイベントを望んでいるのに誰もいない場合は、InternalFrameの作成者に移動して、誰かがイベントを望んでいるかどうかを確認します(など)。
(更新)キーバインディングガイドでこの大胆な警告について疑問に思ったことがある場合:
コンポーネントを検索する順序は予測できないため、WHEN_IN_FOCUSED_WINDOWバインディングの重複は避けてください。
これは、次のセグメントが原因ですKeyboardManager#fireKeyboardAction。
Object tmp = keyMap.get(ks);
if (tmp == null) {
// don't do anything
} else if ( tmp instanceof JComponent) {
...
} else if ( tmp instanceof Vector) { //more than one comp registered for this
Vector v = (Vector)tmp;
// There is no well defined order for WHEN_IN_FOCUSED_WINDOW
// bindings, but we give precedence to those bindings just
// added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW
// bindings are accessed before those of the JRootPane (they
// both have a WHEN_IN_FOCUSED_WINDOW binding for enter).
for (int counter = v.size() - 1; counter >= 0; counter--) {
JComponent c = (JComponent)v.elementAt(counter);
//System.out.println("Trying collision: " + c + " vector = "+ v.size());
if ( c.isShowing() && c.isEnabled() ) { // don't want to give these out
fireBinding(c, ks, e, pressed);
if (e.isConsumed())
return true;
}
}
したがって、検索の順序は実際には予測可能ですが、明らかにこの特定の実装に依存しているため、まったく依存しない方がよいでしょう。予測できないようにしてください。
(JavadocとコードはWinXPのjdk1.6.0_b105からのものです。)