AWT フォーカスサブシステム

Java 2 Standard Edition、JDK 1.4 より前の AWT フォーカスサブシステムは不十分でした。設計と API による大きな問題だけでなく、100 を超える未解決のバグを抱えていました。これらのバグの多くは、プラットフォームの不一致や、重量用のネイティブのフォーカスシステムと軽量用の Java フォーカスシステムとの間に互換性がないことが原因でした。

AWT のフォーカスの実装の単一で最大の問題は、現在フォーカスのある Component を照会することができないことでした。このような照会のための API が存在しないだけではなく、アーキテクチャーが不十分であるために、このような情報はコードによっても維持されていませんでした。

(Frame や Dialog ではなく) Window の軽量な子がキーボード入力を受け取れないことも、同様に問題でした。この問題は、Window が WINDOW_ACTIVATED イベントを決して受け取らないためアクティブになることがなく、フォーカスされた Component を含むことができるのがアクティブな Window のみであるために生じていました。

さらに、FocusEvent および WindowEvent 用の API は、フォーカスまたはアクティブ化の変更に関係する「反対の」Component を決定する方法がないため不十分であることを、多くの開発者が指摘していました。たとえば、Component が FOCUS_LOST イベントを受け取った場合に、どの Component がフォーカスを取得するのかを知る方法はありませんでした。Microsoft Windows はコストなしでこの機能を提供するため、Microsoft Windows C/C++ または Visual Basic から Java に移行する開発者は、この機能がないことに不満を感じていました。

これらおよびその他の欠点に対処するため、JDK 1.4 では AWT の新しいフォーカスモデルを設計しました。主な設計変更は、集中処理のための新しい KeyboardFocusManager クラスの構築、および軽量フォーカスアーキテクチャーです。フォーカス関連のプラットフォーム依存コードは最小限に抑えられ、完全にプラグイン可能で拡張可能な公開 API に置き換えられました。既存の実装との下位互換性を保つ努力をしましたが、洗練され効果的な結果に到達するために、互換性のない小規模な変更を行わざるを得ませんでした。これらの非互換性が既存のアプリケーションに与える影響はわずかであると予測されています。

このドキュメントは、新しい API と、新しいモデルにも引き続き関係する既存の API の正式な仕様です。開発者は、フォーカス関連のクラスおよびメソッドの Javadoc と合わせてこのドキュメントを使用することにより、カスタマイズされていながらプラットフォーム間で一貫性のあるフォーカス動作を持つ堅固な AWT および Swing アプリケーションを作成できるはずです。このドキュメントには次のセクションがあります。

KeyboardFocusManager の概要

フォーカスモデルは、現在のフォーカス状態の照会、フォーカス変更の開始、およびデフォルトのフォーカスイベントディスパッチのカスタムディスパッチャーへの置換をクライアントコードが実行するための API のセットを提供する、単独の KeyboardFocusManager クラスに集中しています。クライアントはフォーカス状態を直接照会することも、フォーカス状態に変更があった場合に PropertyChangeEvent を受け取る PropertyChangeListener を登録することもできます。

KeyboardFocusManager では次の主な概念と用語が導入されます。

  1. 「フォーカス所有者」 -- 通常キーボード入力を受け取る Component。
  2. 「パーマネントフォーカス所有者」 -- フォーカスを永続的に受け取る最後の Component。「フォーカス所有者」と「パーマネントフォーカス所有者」は、テンポラリフォーカス変更が現在有効でないかぎり同等です。変更されている場合、「パーマネントフォーカス所有者」はテンポラリフォーカス変更が終了するとふたたび「フォーカス所有者」になります。
  3. 「フォーカスされた Window」 -- 「フォーカス所有者」を含む Window。
  4. 「アクティブ Window」 -- 「フォーカスされた Window」である Frame または Dialog か、または「フォーカスされた Window」の所有者である最初の Frame または Dialog。
  5. 「フォーカストラバーサル」 -- ユーザーが、カーソルを動かさずに「フォーカス所有者」を変更できる機能。通常、これはキーボード (TAB キーを使用するなど)、またはユーザー補助機能を利用する環境における同等のデバイスを使用して行われます。クライアントコードでは、トラバーサルをプログラムにより開始することもできます。通常のフォーカストラバーサルは、「次の」Component への「フォワード」、または「前の」Component への「バックワード」のいずれかです。
  6. 「フォーカストラバーサルサイクル」 --「フォワード」(または「バックワード」) の通常のフォーカストラバーサルでフォーカスサイクル内のすべての Component をトラバースし、ほかの Component をトラバースしないような、Component 階層の一部分。このサイクルにより、サイクル内の任意の Component から「次の」(フォワードトラバーサル) および「前の」(バックワードトラバーサル) Component へのマッピングが行われます。
  7. 「トラバース可能な Component」 -- フォーカストラバーサルサイクル内の Component。
  8. 「トラバース不可能な Component」 -- フォーカストラバーサルサイクル外の Component。トラバース不可能な Component であっても、ほかの方法 (直接のフォーカスリクエストなど) によってフォーカスが設定可能です。
  9. 「フォーカスサイクルルート」 -- 特定の「フォーカストラバーサルサイクル」の Component 階層のルートである Container。「フォーカス所有者」が特定のサイクル内の Component である場合、通常のフォワードおよびバックワードのフォーカストラバーサルでは、「フォーカス所有者」を Component 階層のフォーカスサイクルルートより上に移動することはできません。代わりに、「アップサイクル」および「ダウンサイクル」という 2 つの追加のトラバーサル操作が定義され、キーボードおよびプログラムによってフォーカストラバーサルサイクル階層を上下にナビゲートできます。
  10. 「フォーカストラバーサルポリシープロバイダ」 - 「FocusTraversalPolicyProvider」プロパティーが true である Container。この Container は、フォーカストラバーサルポリシーを取得するために使用されます。この Container は新しいフォーカスサイクルを定義するわけではなく、その子の「フォワード」および「バックワード」のトラバースの順序を変更するだけです。フォーカストラバーサルポリシープロバイダは、Container に対して setFocusTraversalPolicyProvider を使用して設定できます。

すべての Window および JInternalFrame は、デフォルトで「フォーカスサイクルルート」です。それが唯一のフォーカスサイクルルートである場合は、フォーカス可能なすべての下位 Component がフォーカスサイクルに含まれるべきであり、そのフォーカストラバーサルポリシーは、通常のフォワード (またはバックワード) のトラバーサルの間にすべての下位 Component に到達できることを保証することによって、すべての下位 Component がフォーカスサイクルに含まれるようにするべきです。一方、Window または JInternalFrame にフォーカスサイクルルートである下位 Component がある場合、このような各下位 Component は、自身がルートであるフォーカスサイクルと、もっとも近いフォーカスサイクルルートの上位 Component のフォーカスサイクルの、2 つのフォーカスサイクルのメンバーになります。このような「下位」のフォーカスサイクルルートのフォーカスサイクルに所属するフォーカス可能な Component にトラバースするためには、まず (フォワードまたはバックワードで) トラバースしてその下位のフォーカスサイクルルートに到達し、次に「ダウンサイクル」操作を使用してその下位 Component に到達します。

次はその例です。
次に説明する、ABCF、BDE、および DGH の 3 つのグループ。

次のことを前提にしています。

この例には、合計 3 つのフォーカスサイクルルートがあります。
  1. A はルートであり、ABC、および FA のサイクルのメンバーです。
  2. B はルートであり、BD、および EB のサイクルのメンバーです。
  3. D はルートであり、DG、および HD のサイクルのメンバーです。
デフォルトでフォーカスサイクルルートである Container は Window のみです。 KeyboardFocusManager は abstract クラスです。AWT では、DefaultKeyboardFocusManager クラスにデフォルトの実装が提供されます。

KeyboardFocusManager とブラウザコンテキスト

一部のブラウザは、異なるコードベースのアプレットを別のコンテキストに分割し、これらのコンテキストの間に壁を構築します。各スレッドおよび各 Component は、特定のコンテキストに関連付けられ、ほかのコンテキスト内のスレッドに影響を与えたり、Component にアクセスしたりすることはできません。このようなシナリオでは、コンテキストごとに 1 つの KeyboardFocusManager があります。別のブラウザは、すべてのアプレットを同じコンテキストに配置します。これは、すべてのアプレットに対して単一でグローバルな KeyboardFocusManager のみがあることを示します。この動作は実装に依存します。詳細はブラウザのドキュメントを参照してください。ただし、存在するコンテキストの数にかかわらず、ClassLoader あたり複数のフォーカス所有者、フォーカスされた Window、またはアクティブ Window が存在することはありません。

KeyEventDispatcher および KeyEventPostProcessor

ユーザーの KeyEvent は通常フォーカス所有者に送られますが、これを避けるべき場合がまれにあります。インプットメソッドは特殊な Component の例で、インプットメソッドが KeyEvent を受け取るべきですが、関連付けられたテキスト Component は引き続きフォーカス所有者でありフォーカス所有者であるべきです。

KeyEventDispatcher は、クライアントコードが特定のコンテキスト内のすべての KeyEvent を事前に待機できるようにするための、軽量インタフェースです。このインタフェースを実装し、現在の KeyboardFocusManager に登録されたクラスのインスタンスは、フォーカス所有者に KeyEvent がディスパッチされる前にその KeyEvent を受け取ります。これにより、KeyEventDispatcher はイベントのターゲット変更、消費、自身によるイベントディスパッチ、またはその他の変更を行うことができます。

一貫性を保つため、KeyboardFocusManager 自体は KeyEventDispatcher です。デフォルトで、現在の KeyboardFocusManager は、登録された KeyEventDispatcher によりディスパッチされないすべての KeyEvent を受信します。現在の KeyboardFocusManager は KeyEventDispatcher としての登録を完全に解除することはできません。ただし、KeyEventDispatcher が、実際に KeyEvent をディスパッチしたかどうかにかかわらず、KeyEvent をディスパッチしたことを報告した場合は、KeyboardFocusManager は KeyEvent に関してそれ以上の処理を行いません (クライアントコードは、現在の KeyboardFocusManager を KeyEventDispatcher として 1 回または複数回登録することが可能ですが、これが必要になる明確な理由はなく、お勧めできません)。

クライアントコードは、KeyEventPostProcessor インタフェースを使用して、特定のコンテキスト内の KeyEvent を事後に待機することもできます。現在の KeyboardFocusManager に登録された KeyEventPostProcessor は、KeyEvent がフォーカス所有者にディスパッチされ処理されたあとでその KeyEvent を受け取ります。KeyEventPostProcessor は、アプリケーション内に現在フォーカスを所有している Component がないために破棄されるはずの KeyEvent も受け取ります。これによりアプリケーションは、メニューショートカットなどの、グローバル KeyEvent の事後処理を必要とする機能を実装できるようになります。

KeyEventDispatcher と同様に、KeyboardFocusManager も KeyEventPostProcessor を実装し、この機能を使用する際には同様の制限が適用されます。

FocusEvent と WindowEvent

AWT では、フォーカスモデルの中心となる次の 6 つのイベントタイプが 2 つの異なる java.awt.event クラス内に定義されています。

  1. WindowEvent.WINDOW_ACTIVATED: このイベントは、Frame または Dialog がアクティブ Window になったときに、その Frame または Dialog にディスパッチされます (Frame でも Dialog でもない Window にはディスパッチされません)。
  2. WindowEvent.WINDOW_GAINED_FOCUS: このイベントは、Window がフォーカスされた Window になったときにディスパッチされます。このイベントを受け取ることができるのは、フォーカス可能な Window のみです。
  3. FocusEvent.FOCUS_GAINED: このイベントは、Component がフォーカス所有者になったときにディスパッチされます。このイベントを受け取ることができるのは、フォーカス可能な Component のみです。
  4. FocusEvent.FOCUS_LOST: このイベントは、Component がフォーカス所有者でなくなったときにディスパッチされます。
  5. WindowEvent.WINDOW_LOST_FOCUS: このイベントは、Window がフォーカスされた Window でなくなったときにディスパッチされます。
  6. WindowEvent.WINDOW_DEACTIVATED: このイベントは、Frame または Dialog がアクティブ Window でなくなったときに、その Frame または Dialog にディスパッチされます (Frame でも Dialog でもない Window にはディスパッチされません)。

イベント配信

フォーカスが java アプリケーションにない場合に、ユーザーが非アクティブな Frame b のフォーカス可能な子 Component a をクリックすると、次のイベントがディスパッチされ、順に処理されます。

  1. bWINDOW_ACTIVATED イベントを受信します。
  2. 次に、bWINDOW_GAINED_FOCUS イベントを受信します。
  3. 最後に、aFOCUS_GAINED イベントを受信します。
その後、ユーザーが別の Frame d のフォーカス可能な子 Component c をクリックすると、次のイベントがディスパッチされ、順に処理されます。
  1. aFOCUS_LOST イベントを受信します。
  2. bWINDOW_LOST_FOCUS イベントを受信します。
  3. bWINDOW_DEACTIVATED イベントを受信します。
  4. dWINDOW_ACTIVATED イベントを受信します。
  5. dWINDOW_GAINED_FOCUS イベントを受信します。
  6. cFOCUS_GAINED イベントを受信します。
各イベントは、次のイベントがディスパッチされる前に完全に処理されます。この制限は、Component が別のコンテキストにあり、別のイベントディスパッチスレッドで処理される場合でも適用されます。

さらに、各イベントタイプは反対のイベントタイプと一対一対応でディスパッチされます。たとえば、Component が FOCUS_GAINED イベントを受け取った場合、間に FOCUS_LOST を受け取ることなく別の FOCUS_GAINED イベントを受け取ることは決してありません。

最後に、これらのイベントは情報目的だけで配信されることに注意してください。たとえば、前の FOCUS_LOST イベントの処理中に、フォーカスを失う Component にフォーカスを戻すことをリクエストすることによって、保留中の FOCUS_GAINED イベントが配信されることを防ぐことはできません。クライアントコードがこのようなリクエストを行う場合があっても、保留中の FOCUS_GAINED は配信され、フォーカスを元のフォーカス所有者に戻すイベントがあとに続きます。

FOCUS_GAINED イベントをどうしても抑制する必要がある場合は、クライアントコードはフォーカスの変更を拒否する VetoableChangeListener をインストールできます。「フォーカスと VetoableChangeListener」を参照してください。

反対の Component と Window

各イベントには、フォーカスまたはアクティベーションの変更に関係する「反対の」Component または Window の情報が含まれます。たとえば、FOCUS_GAINED イベントの場合、反対の Component はフォーカスを失った Component です。このフォーカスまたはアクティベーションの変更が、ネイティブアプリケーションや異なる VM またはコンテキストの Java アプリケーションで発生する場合、または別の Component なしで行われる場合は、反対の Component または Window は null になります。この情報には、FocusEvent.getOppositeComponent または WindowEvent.getOppositeWindow を使用してアクセスできます。

一部のプラットフォームでは、フォーカスまたはアクティベーションの変更が 2 つの異なる重量 Component 間で起きた場合に、反対の Component または Window を判断できません。このような場合に、反対の Component または Window が null にセットされるプラットフォームもあれば、null 以外の有効な値にセットされるプラットフォームもあります。ただし、同じ重量 Container を共有する 2 つの軽量 Component 間のフォーカスの変更では、反対の Component は常に正しくセットされます。したがって、純粋な Swing アプリケーションでは、トップレベル Window 内で発生したフォーカス変更の反対の Component を使用する場合にはこのプラットフォームの制限を無視できます。

テンポラリ FocusEvent

FOCUS_GAINED および FOCUS_LOST イベントは、テンポラリまたはパーマネントとマークされます。

テンポラリ FOCUS_LOST イベントは、Component がフォーカスを失おうとしているが、すぐにフォーカスを取得し直す場合に送信されます。これらのイベントは、フォーカスの変更がデータ検証のトリガーとして使用される場合に便利です。たとえば、テキスト Component が、ユーザーがほかの Component との対話を開始する前にそのコンテンツをコミットする場合がありますが、これは FOCUS_LOST イベントに応答することで実行できます。ただし、受け取った FocusEvent がテンポラリの場合は、すぐにテキストフィールドにフォーカスが戻るため、コミットするべきではありません。

パーマネントフォーカス移動は通常、ユーザーが選択可能な重量 Component をクリックした場合や、キーボードまたは同等の入力デバイスを使用したフォーカストラバーサル、または requestFocus()requestFocusInWindow() の呼び出しの結果生じます。

テンポラリフォーカス移動は通常、Menu または PopupMenu の表示、Scrollbar のクリックまたはドラッグ、タイトルバーのドラッグによる Window の移動、またはフォーカスされた Window の別の Window への変更を行なった結果生じます。一部のプラットフォームでは、これらのアクションでは FocusEvent がまったく生成されない場合があることに注意してください。ほかのプラットフォームでは、テンポラリフォーカス移動が発生します。

Component がテンポラリ FOCUS_LOST イベントを受け取ると、イベントの反対の Component (ある場合) はテンポラリ FOCUS_GAINED イベントを受け取る場合がありますが、パーマネント FOCUS_GAINED イベントを受け取る場合もあります。Menu または PopupMenu の表示や Scrollbar のクリックまたはドラッグでは、テンポラリ FOCUS_GAINED イベントが生成されるはずです。しかし、フォーカスされた Window の変更では、新しいフォーカス所有者に対してパーマネント FOCUS_GAINED イベントが生成されます。

Component クラスには、必要なテンポラリ状態をパラメータとして取る requestFocus および requestFocusInWindow のバリエーションが含まれます。ただし一部のネイティブウィンドウシステムでは、任意のテンポラリ状態の指定を実装できないため、このメソッドの正常な動作は軽量 Component に対してのみ保証されます。このメソッドは一般的な用途向きではありませんが、Swing のような軽量 Component ライブラリ用のフックとして用意されています。

フォーカストラバーサル

各 Component は、指定されたトラバーサル操作に対して、独自のフォーカストラバーサルキーのセットを定義します。Component は、フォワードおよびバックワードのトラバーサル用に別個のキーのセットをサポートし、1 つ上のフォーカストラバーサルサイクルに移動するためのキーのセットもサポートします。フォーカスサイクルルートである Container は、1 つ下のフォーカストラバーサルサイクルに移動するためのキーのセットもサポートします。Component に対してセットが明示的に定義されていない場合、その Component は親から再帰的にセットを継承し、最終的には現在の KeyboardFocusManager のコンテキスト全体のデフォルトセットを継承します。

AWTKeyStroke API を使用すると、2 つの特定の KeyEvent (KEY_PRESSEDKEY_RELEASED) のどちらでフォーカストラバーサルが発生するかをクライアントコードで指定できます。ただし、指定される KeyEvent に関係なく、関連付けられる KEY_TYPED イベントを含む、フォーカストラバーサルキーに関連するすべての KeyEvent は消費され、ほかの Component へのディスパッチは行われません。KEY_TYPED イベントのフォーカストラバーサル操作へのマッピング、任意の Component または KeyboardFocusManager のデフォルトに対して同一イベントの複数のフォーカストラバーサル操作へのマッピングは実行時エラーになります。

デフォルトのフォーカストラバーサルキーは実装に依存します。Sun では、特定のネイティブなプラットフォームに対するすべての実装で同じキーを使用することをお勧めします。Windows および Unix に対する推奨は次にリストされています。

Component は、フォーカストラバーサルキーを Component.setFocusTraversalKeysEnabled を使用してすべてまとめて有効または無効にできます。フォーカストラバーサルキーが無効の場合、Component はこれらのキーに対するすべての KeyEvent を受け取ります。フォーカストラバーサルキーが有効の場合、Component はトラバーサルキーの KeyEvent を受け取ることはなく、KeyEvent はフォーカストラバーサル操作に自動的にマッピングされます。

通常のフォワードおよびバックワードのトラバーサルでは、AWT のフォーカスの実装は、次にどの Component にフォーカスするかを、フォーカス所有者のフォーカスサイクルルートまたはフォーカストラバーサルポリシープロバイダの FocusTraversalPolicy に基づいて決定します。フォーカス所有者がフォーカスサイクルのルートの場合、通常のフォーカストラバーサルの間にどの Component が次または前の Component を表すかについて、あいまいになる場合があります。したがって、現在の KeyboardFocusManager は「現在の」フォーカスサイクルルートへの参照を維持しており、これはすべてのコンテキストにまたがってグローバルです。現在のフォーカスサイクルルートは、あいまいさを解決するために使用されます。

アップサイクルトラバーサルでは、フォーカス所有者は、現在のフォーカス所有者のフォーカスサイクルルートに設定され、現在のフォーカスサイクルルートは新しいフォーカス所有者のフォーカスサイクルルートに設定されます。ただし、現在のフォーカス所有者のフォーカスサイクルルートがトップレベルウィンドウの場合、フォーカス所有者はフォーカスサイクルルートのデフォルトでフォーカスするコンポーネントに設定され、現在のフォーカスサイクルルートは変更されません。

ダウンサイクルトラバーサルでは、現在のフォーカス所有者がフォーカスサイクルルートである場合は、フォーカス所有者は、現在のフォーカス所有者のデフォルトでフォーカスするコンポーネントに設定され、現在のフォーカスサイクルルートは現在のフォーカス所有者に設定されます。現在のフォーカス所有者がフォーカスサイクルルートではない場合、フォーカストラバーサル操作は行われません。

FocusTraversalPolicy

FocusTraversalPolicy は、あるフォーカスサイクルルートまたはフォーカストラバーサルポリシープロバイダ内の Component のトラバース順序を定義します。FocusTraversalPolicy のインスタンスは Container 間で共有できるため、それらの Container は同じトラバーサルポリシーを実装できます。FocusTraversalPolicy は、フォーカストラバーサルサイクル階層が変わっても再度初期化する必要はありません。

FocusTraversalPolicy は、次の 5 つのアルゴリズムを定義する必要があります。

  1. フォーカスサイクルルートとそのサイクル内の Component a が指定された場合の、a の次の Component。
  2. フォーカスサイクルルートとそのサイクル内の Component a が指定された場合の、a の前の Component。
  3. フォーカスサイクルルートが指定された場合の、そのサイクルの「最初の」Component。「最初の」Component は、フォワード方向のトラバーサルがラップするときに、フォーカスする Component です。
  4. フォーカスサイクルルートが指定された場合の、そのサイクルの「最後の」Component。「最後の」Component は、バックワード方向のトラバーサルがラップするときに、フォーカスする Component です。
  5. フォーカスサイクルルートが指定された場合の、そのサイクルの「デフォルト」Component。「デフォルト」Component は、下にトラバースして新しいフォーカストラバーサルサイクルが開始されたときに、最初にフォーカスが設定される Component です。これは「最初の」Component と同じ場合もありますが、同じである必要はありません。

FocusTraversalPolicy は、オプションで次のアルゴリズムを提供する場合もあります。

Window が指定された場合の、その Window 内の「初期」Component。初期 Component は Window が最初に表示されたときに最初にフォーカスを受け取ります。デフォルトでは、「デフォルト」Component と同じです。
さらに、Swing は FocusTraversalPolicy のサブクラス InternalFrameFocusTraversalPolicy を提供し、開発者はこれを使用して次のアルゴリズムを提供できます。
JInternalFrame が指定された場合の、その JInternalFrame の「初期」Component。初期 Component は JInternalFrame が最初に選択されたときに最初にフォーカスを受け取ります。デフォルトでは、JInternalFrame のデフォルトでフォーカスする Component と同じです。
FocusTraversalPolicy は、Container.setFocusTraversalPolicy を使用して Container にインストールされます。ポリシーが明示的に設定されていない場合は、Container はもっとも近いフォーカスサイクルルートの上位 Container からポリシーを継承します。トップレベルは、コンテキストのデフォルトポリシーを使用してフォーカストラバーサルポリシーを初期化します。コンテキストのデフォルトポリシーは、KeyboardFocusManager.setDefaultFocusTraversalPolicy を使用して確立されます。

AWT は、クライアントコードで使用できる 2 つの標準 FocusTraversalPolicy 実装を提供します。

  1. ContainerOrderFocusTraversalPolicy: フォーカストラバーサルサイクル内の Component すべてを、Component が Container に追加された順で反復します。各 Component は、accept(Component) メソッドを使用して適合性をテストされます。デフォルトでは、Component は可視性、表示可能性、有効性、フォーカス可能性のすべてを満たす場合にのみ適合します。
  2. デフォルトでは、ContainerOrderFocusTraversalPolicy は暗黙にフォーカスを下のサイクルに転送します。つまり、通常のフォワードフォーカストラバーサル中は、フォーカスサイクルルートがトラバース可能またはトラバース不可能のどちらの Container であるかには関係なく、フォーカスサイクルルートのあとにトラバースされた Component が、そのフォーカスサイクルルートのデフォルトでフォーカスする Component になります (下の図 1、2 を参照)。このような動作により、アップサイクルおよびダウンサイクルトラバーサルの概念なしで設計されたアプリケーションとの、下位互換性が提供されます。
  3. DefaultFocusTraversalPolicy: 適合性テストを再定義する ContainerOrderFocusTraversalPolicy のサブクラス。クライアントコードの Component.isFocusTraversable() または Component.isFocusable() のオーバーライド、または Component.setFocusable(boolean) の呼び出しによって、Component のフォーカス可能性を明示的に設定した場合は、DefaultFocusTraversalPolicyContainerOrderFocusTraversalPolicy とまったく同じように動作します。デフォルトのフォーカス可能性を使用する場合は、DefaultFocusTraversalPolicy はフォーカス不可能なピアを持つコンポーネントをすべて拒否します。
    ピアがフォーカス可能かどうかは実装で決定されます。Sun では、特定のネイティブプラットフォームのすべての実装に対して、フォーカス可能性が同じピアの構築をお勧めします。Windows および Unix については、Canvas、Label、Panel、Scrollbar、ScrollPane、Window、軽量 Component に対してはフォーカス不可能なピアを、それ以外の Component についてはフォーカス可能なピアをお勧めします。これらの推奨は Sun AWT の実装で使用されます。Component のピアのフォーカス可能性は、Component 自体のフォーカス可能性とは異なり、また影響も与えません。

Swing は、クライアントコードで使用する 2 つの追加の標準 FocusTraversalPolicy 実装を提供します。各実装は InternalFrameFocusTraversalPolicy です。

  1. SortingFocusTraversalPolicy: 特定の Comparator に基づいてフォーカストラバーサルサイクルの Component をソートすることによってトラバーサルの順序を判定します。各 Component は、accept(Component) メソッドを使用して適合性をテストされます。デフォルトでは、Component は可視性、表示可能性、有効性、フォーカス可能性のすべてを満たす場合にのみ適合します。
  2. デフォルトでは、SortingFocusTraversalPolicy は暗黙にフォーカスを下のサイクルに転送します。つまり、通常のフォワードフォーカストラバーサル中は、フォーカスサイクルルートがトラバース可能またはトラバース不可能のどちらの Container であるかには関係なく、フォーカスサイクルルートのあとにトラバースされた Component が、そのフォーカスサイクルルートのデフォルトでフォーカスする Component になります (下の図 1、2 を参照)。このような動作により、アップサイクルおよびダウンサイクルトラバーサルの概念なしで設計されたアプリケーションとの、下位互換性が提供されます。
  3. LayoutFocusTraversalPolicy: サイズ、位置、方向に基づいて Component をソートする SortingFocusTraversalPolicy のサブクラスです。Component は、サイズと位置に基づいて、大まかに行と列に分類されます。水平方向の Container の場合、列は左から右または右から左に並べられ、行は上から下に並べられます。垂直方向の Container の場合、列は上から下に並べられ、行は左から右または右から左に並べられます。行内の列がすべてトラバースされてから、次の行に進みます。
    さらに、適合性テストは拡張され、空の InputMap を持つかまたは継承する JComponent を除外します。

次の図は、暗黙的なフォーカス移動を示します。
暗黙的なフォーカス移動。
次のことを前提にしています。

標準 Look&Feel または BasicLookAndFeel から派生した Look&Feel を使用する Swing アプリケーションまたは Swing/AWT の混合アプリケーションは、デフォルトですべての Container に対して LayoutFocusTraversalPolicy を使用します。

純粋な AWT アプリケーションを含むその他のすべてのアプリケーションは、デフォルトで DefaultFocusTraversalPolicy を使用します。

フォーカストラバーサルポリシープロバイダ

フォーカスサイクルルートでない Container には、独自の FocusTraversalPolicy を提供するオプションがあります。そのためには、次の呼び出しで、Container のフォーカストラバーサルポリシープロバイダプロパティーを true に設定する必要があります。

Container がフォーカストラバーサルポリシープロバイダであるかどうかを判断するには、次のメソッドを使用するべきです。 フォーカストラバーサルポリシープロバイダプロパティーがフォーカスサイクルルートに設定されている場合、フォーカストラバーサルポリシープロバイダとはみなされず、ほかのフォーカスサイクルルートと同様に動作します。

フォーカスサイクルルートとフォーカストラバーサルポリシープロバイダの間の主な違いは、後者はほかのすべての Container と同様に、フォーカスの出入りを許可することです。ただし、フォーカストラバーサルポリシープロバイダ内の子は、プロバイダの FocusTraversalPolicy によって決定される順序でトラバースされます。フォーカストラバーサルポリシープロバイダがこの方法で動作するようにするために、FocusTraversalPolicy はこれらを次のように処理します。

プログラムによるトラバーサル

ユーザーが開始するフォーカストラバーサルに加えて、クライアントコードでフォーカストラバーサル操作をプログラムにより開始することもできます。クライアントコードでは、プログラムによるトラバーサルはユーザーが開始するトラバーサルと区別できません。プログラムによるトラバーサルの開始に推奨される方法は、KeyboardFocusManager の次のメソッドのいずれかを使用することです。

これらの各メソッドは、現在のフォーカス所有者のトラバーサル操作を開始します。現在フォーカス所有者が存在しない場合は、トラバーサル操作は生じません。さらに、フォーカス所有者がフォーカスサイクルルートではない場合、downFocusCycle() はトラバーサル操作を実行しません。

KeyboardFocusManager は、これらのメソッドの次のバリエーションもサポートします。

これらの各メソッドは、フォーカス所有者ではなく指定された Component のトラバーサル操作を開始します。つまり、指定された Component がフォーカス所有者であるかのようにトラバーサルが起こります (フォーカス所有者である必要はありません)。

代替の同等な API が Component クラスおよび Container クラス自体にも定義されています。

KeyboardFocusManager のバリエーションと同様に、これらの各メソッドは、その Component がフォーカス所有者であるかのようにトラバーサル操作を開始します (フォーカス所有者である必要はありません)。

また、フォーカス所有者を、直接または上位 Component を経由して間接的に非表示または無効にしたり、表示不可能またはフォーカス不可能にしたりすると、自動的にフォワードフォーカストラバーサルが開始されます。上位の軽量または重量 Component を非表示にすると、その子は常に間接的に非表示になりますが、上位の重量 Component を無効にした場合のみ、その子が無効になります。したがって、フォーカス所有者の上位の軽量 Component を無効にしても、フォーカストラバーサルは自動的には開始されません。

クライアントコードがフォーカストラバーサルを開始し、ほかにフォーカスする Component がない場合、フォーカス所有者は変更されません。クライアントコードがフォーカス所有者を直接または間接的に非表示にするか、またはフォーカス所有者を表示不可能またはフォーカス不可能にすることによって自動的なフォーカストラバーサルを開始し、ほかにフォーカスする Component がない場合、グローバルフォーカス所有者はクリアされます。クライアントコードがフォーカス所有者を直接または間接的に無効することによって自動的なフォーカストラバーサルを開始し、ほかにフォーカスする Component がない場合、フォーカス所有者は変更されません。

フォーカス可能性

フォーカス可能な Component は、フォーカス所有者になることができ (「フォーカス可能性」)、FocusTraversalPolicy を使用してキーボードフォーカストラバーサルに参加します (「フォーカストラバーサル可能性」)。2 つの概念に区別はなく、Component はフォーカス可能かつフォーカストラバーサル可能であるか、またはどちらも不可能である必要があります。 Component は、isFocusable() メソッドを介してこの状態を表します。デフォルトでは、すべての Component がこのメソッドから true を返します。クライアントコードは、Component.setFocusable(boolean) を呼び出すことでこのデフォルトを変更できます。

フォーカス可能な Window

パレットウィンドウおよびインプットメソッドをサポートするために、クライアントコードは Window がフォーカスされた Window にならないようにすることができます。移行性によって、Window またはその下位 Component がフォーカス所有者になることを防ぎます。フォーカス不可能な Window は、フォーカス可能な Window を引き続き所有できます。デフォルトでは、すべての Frame および Dialog はフォーカス可能です。もっとも近くの所有する Frame または Dialog が画面に表示されており、フォーカストラバーサルサイクルに少なくともその 1 つの Component が含まれる場合、Frame でも Dialog でもない Window についてもすべて、デフォルトでフォーカス可能です。Window をフォーカス不可能にするには、Window.setFocusableWindowState(false) を使用します。

Window がフォーカス不可能の場合、この制約は KeyboardFocusManager が Window の WINDOW_GAINED_FOCUS イベントを検知したときに実施されます。この時点で、フォーカス変更は拒否され、フォーカスは別の Window にリセットされます。拒否復旧スキームは、VetoableChangeListener がフォーカス変更を拒否した場合と同じです。「フォーカスと VetoableChangeListener」を参照してください。

新しいフォーカスの実装では、Window またはその下位 Component の KeyEvent が Window の所有者の子を介してプロキシされる必要があり、イベントを受け取るためにこのプロキシが X11 上でマップされている必要があるため、もっとも近くの所有する Frame または Dialog が表示されていない Window は、X11 で KeyEvent を決して受け取れません。この制約をサポートするために、Window の「ウィンドウフォーカス可能性」とその「ウィンドウフォーカス可能性状態」とを区別しました。Window のフォーカス可能性状態と Window のもっとも近くの所有する Frame または Dialog の表示状態を組み合わせて、Window のフォーカス可能性が判断されます。デフォルトで、すべての Window は true のフォーカス可能性状態を持っています。Window のフォーカス可能性状態を false に設定すると、もっとも近くの所有する Frame または Dialog の表示状態にかかわらず、フォーカスされた Window にならないことが保証されます。

Swing では、アプリケーションは null の所有者を持つ JWindow を作成できます。Swing では、このようなすべての JWindow は private で非表示の Frame に所有されるように構築されます。この Frame の表示状態は常に false になるため、null の所有者で構築された JWindow は、Window のフォーカス可能性状態が true であっても、フォーカスされた Window になることは決してできません。

フォーカスされた Window がフォーカス不可能になった場合は、AWT は、Window の所有者の直近にフォーカスされた Component にフォーカスしようとします。したがって、Window の所有者が新しくフォーカスされた Window になります。Window の所有者もフォーカス不可能な Window である場合は、フォーカス変更リクエストは所有者の階層を再帰的に上に移動します。すべてのプラットフォームが Window をまたがるフォーカス変更をサポートするわけではないので (「フォーカスのリクエスト」を参照)、このようなフォーカス変更リクエストがすべて失敗する可能性があります。この場合、グローバルフォーカス所有者はクリアされ、フォーカスされた Window は変更されません。

フォーカスのリクエスト

Component は、フォーカス所有者になることを Component.requestFocus() の呼び出しによってリクエストできます。これにより、Component が表示可能、フォーカス可能、可視で、すべての上位 Component (トップレベル Window を除く) が可視である場合にかぎり、Component へのパーマネントフォーカス転送が開始されます。これらの条件のいずれかが満たされない場合は、リクエストはただちに拒否されます。無効な Component がフォーカス所有者になる場合もありますが、この場合は、すべての KeyEvent は破棄されます。

Component のトップレベル Window がフォーカスされた Window ではなく、プラットフォームが Window 間でのフォーカスのリクエストをサポートしない場合にも、リクエストは拒否されます。この理由でリクエストが拒否された場合、リクエストは記憶され、あとでその Window がユーザーによってフォーカスされたときに許可されます。それ以外の場合、フォーカス変更リクエストによって、フォーカスされた Window も変更されます。

フォーカス変更リクエストが許可されたかどうかを同期的に判断する方法はありません。代わりに、クライアントコードは FocusListener を Component にインストールし、FOCUS_GAINED イベントの配信を監視する必要があります。クライアントコードでは、このイベントを受け取るまで、Component がフォーカス所有者であるとみなしてはいけません。イベントは、requestFocus() が戻る前に配信されるとはかぎりません。開発者は、いずれかの動作を想定してはいけません。

AWT は、すべてのフォーカス変更リクエストが EventDispatchThread で行われる場合には、先打ちをサポートします。クライアントコードがフォーカスの変更をリクエストし、AWT がこのリクエストはネイティブウィンドウシステムによって許可されるものであると判定した場合、AWT は現在の KeyboardFocusManager に対して、現在処理中のイベントのタイムスタンプよりもあとのタイムスタンプですべての KeyEvent をキューに入れるべきであることを通知します。これらの KeyEvent は、新しい Component がフォーカス所有者になるまでディスパッチされません。AWT は、フォーカス変更がネイティブレベルで成功しなかった場合、Component のピアが破棄された場合、および VetoableChangeListener によってフォーカス変更が拒否された場合は、遅延されたディスパッチリクエストを取り消します。KeyboardFocusManager は、フォーカス変更リクエストが EventDispatchThread 以外のスレッドから行われた場合、先打ちをサポートする必要はありません。

Component.requestFocus() はプラットフォーム間で一貫した方法で実装できないため、開発者は代わりに Component.requestFocusInWindow() を使用することが推奨されます。このメソッドは、すべてのプラットフォーム上で Window 間のフォーカス移動を自動的に拒否します。フォーカス移動のプラットフォーム固有の唯一の要素を排除することで、このメソッドはプラットフォーム間で一貫した動作を実現します。

さらに、requestFocusInWindow() はブール値を返します。「false」が返された場合、リクエストは確実に失敗します。「true」が返された場合、通常、リクエストは正常に処理されます。ただし、許可されない、または Component のピアが破棄されるなどの異常なイベントが、ネイティブのウィンドウシステムでリクエストを許可する前に発生した場合は正常に処理されません。「true」が返された場合、リクエストは正常に処理される可能性が高いのですが、この Component が FOCUS_GAINED イベントを受け取るまでは、この Component がフォーカス所有者であることを決して想定しないでください。

クライアントコードで、アプリケーション内のどの Component もフォーカス所有者にしない場合は、現在の KeyboardFocusManager のメソッド KeyboardFocusManager. clearGlobalFocusOwner() を呼び出すことができます。このメソッドが呼び出されたときにフォーカス所有者が存在する場合、フォーカス所有者はパーマネント FOCUS_LOST イベントを受け取ります。これ以降、AWT フォーカス実装は、ユーザーまたはクライアントコードが明示的にフォーカスを Component に設定するまで、すべての KeyEvent を破棄します。

Component クラスは、クライアントコードがテンポラリ状態を指定できる requestFocus および requestFocusInWindow のバリエーションもサポートします。テンポラリ FocusEvents を参照してください

フォーカスと PropertyChangeListener

クライアントコードは、PropertyChangeListener を介して、コンテキスト全体でのフォーカス状態の変更や、Component 内のフォーカス関連の状態の変更を待機できます。

KeyboardFocusManager は次のプロパティーをサポートしています。

  1. focusOwner: フォーカス所有者
  2. focusedWindow: フォーカスされた Window
  3. activeWindow: アクティブ Window
  4. defaultFocusTraversalPolicy: デフォルトのフォーカストラバーサルポリシー
  5. forwardDefaultFocusTraversalKeys: デフォルトの FORWARD_TRAVERSAL_KEYS のセット
  6. backwardDefaultFocusTraversalKeys: デフォルトの BACKWARD_TRAVERSAL_KEYS のセット
  7. upCycleDefaultFocusTraversalKeys: デフォルトの UP_CYCLE_TRAVERSAL_KEYS のセット
  8. downCycleDefaultFocusTraversalKeys: デフォルトの DOWN_CYCLE_TRAVERSAL_KEYS のセット
  9. currentFocusCycleRoot: 現在のフォーカスサイクルルート

現在の KeyboardFocusManager にインストールされた PropertyChangeListener は、フォーカス所有者、フォーカスされた Window、アクティブ Window、および現在のフォーカスサイクルルートがすべてのコンテキストで共有されるグローバルフォーカス状態を構成するにもかかわらず、KeyboardFocusManager のコンテキスト内のこれらの変更のみを検知します。これは、クライアントコードが PropertyChangeListener をインストールする前にセキュリティーチェックにパスすることを義務付けるよりはわずらわしくないと考えられます。

Component は次のフォーカス関連のプロパティーをサポートしています。

  1. focusable: Component のフォーカス可能性
  2. focusTraversalKeysEnabled: Component のフォーカストラバーサルキーの (有効かどうかの) 状態
  3. forwardFocusTraversalKeys: Component の FORWARD_TRAVERSAL_KEYS のセット
  4. backwardFocusTraversalKeys: Component の BACKWARD_TRAVERSAL_KEYS のセット
  5. upCycleFocusTraversalKeys: Component の UP_CYCLE_TRAVERSAL_KEYS のセット

Container は、Component のプロパティーに加えて次のフォーカス関連のプロパティーをサポートしています。

  1. downCycleFocusTraversalKeys: Container の DOWN_CYCLE_TRAVERSAL_KEYS のセット
  2. focusTraversalPolicy: Container のフォーカストラバーサルポリシー
  3. focusCycleRoot: Container のフォーカスサイクルルートの状態

Window は、Container のプロパティーに加えて次のフォーカス関連のプロパティーをサポートしています。

  1. focusableWindow: Window のフォーカス可能な Window 状態

Window にインストールされた PropertyChangeListener は、focusCycleRoot プロパティーの PropertyChangeEvent を決して検出しません。Window は常にフォーカスサイクルルートであり、このプロパティーは変更できません。

フォーカスと VetoableChangeListener

KeyboardFocusManager は次のプロパティーに対して VetoableChangeListener もサポートしています。

  1. "focusOwner":フォーカス所有者
  2. "focusedWindow":フォーカスされた Window
  3. "activeWindow":アクティブ Window
VetoableChangeListener が、PropertyVetoException をスローすることによってフォーカスまたはアクティブ化の変更を拒否すると、変更は中止されます。変更をすでに承認した VetoableChangeListener がある場合、その VetoableChangeListener は状態を以前の値に復帰することを示す PropertyChangeEvent を非同期的に受け取ります。

VetoableChangeListener は、KeyboardFocusManager で変更が反映される前に状態変更の通知を受けます。逆に、PropertyChangeListener は変更が反映されたあとで通知を受け取ります。したがって、すべての VetoableChangeListener はどの PropertyChangeListener よりも前に通知を受け取ります。

VetoableChangeListener はべき等である必要があり、特定のフォーカス変更に関して喪失と取得の両方のイベントを拒否する必要があります (FOCUS_LOSTFOCUS_GAINED など)。たとえば、VetoableChangeListenerFOCUS_LOST イベントを拒否する場合、KeyboardFocusManagerEventQueue を検索して関連する保留中の FOCUS_GAINED イベントを削除する必要はありません。代わりに、KeyboardFocusManager はこのイベントをディスパッチすることができ、このイベントを同様に拒否することは VetoableChangeListener の責任です。さらに、FOCUS_GAINED イベントの処理中に、KeyboardFocusManager が別の FOCUS_LOST イベントを合成することによってグローバルフォーカス状態を再同期しようとする場合があります。このイベントは最初の FOCUS_LOST イベントと同様に拒否される必要があります。

KeyboardFocusManager は、PropertyChangeListener に状態変更を通知する間、ロックを保持しません。ただし、この要件は VetoableChangeListeners に関しては緩和されます。したがって、クライアント定義の VetoableChangeListener は、デッドロックが発生する可能性があるので、vetoableChange(PropertyChangeEvent) 内で追加のロックを取得することを避けるべきです。 フォーカスまたはアクティブ化の変更が拒否されると、KeyboardFocusManager は拒否回復を次のように開始します。

VetoableChangeListener は、拒否回復の結果として開始されたフォーカス変更を拒否しないように注意する必要があります。この状況を想定しないと、拒否されたフォーカス変更と回復の試行の無限サイクルに陥ることがあります。

Z 軸順

一部のネイティブウィンドウシステムでは、Window の Z 軸順がフォーカス状態またはアクティブ状態 (該当する場合) に影響することがあります。Microsoft Windows では、最前面の Window は当然フォーカスされた Window でもあります。しかし Solaris では、多くのウィンドウマネージャーが、フォーカスされた Window を決定するときに、ポイントしてフォーカスするモデルを使用し、Z 軸順を無視します。 Window をフォーカスまたはアクティブ化するとき、AWT はネイティブプラットフォームの UI 要件に準拠します。したがって、Z 軸順に関連する次のようなメソッドのフォーカスの動作は、

プラットフォームに依存します。JDK 1.4 では、Microsoft Windows および Solaris 上でのこれらのメソッドの動作は次のとおりです。

DefaultKeyboardFocusManager の置き換え

KeyboardFocusManager は、ブラウザコンテキストレベルでプラグイン可能です。クライアントコードは、KeyboardFocusManager または DefaultKeyboardFocusManager をサブクラス化して、フォーカス、FocusEvent、および KeyEvent に関連する WindowEvent の処理方法とディスパッチ方法を変更できます。また、グローバルフォーカス状態を調べて変更できます。カスタムの KeyboardFocusManager は、FocusListener や WindowListener では不可能な根本的なレベルで、フォーカス変更を拒否することもできます。

KeyboardFocusManager を全体的に置き換えると、開発者はフォーカスモデルを完全に制御できますが、これは、ピアフォーカスレイヤーを完全に理解することが必要な困難なプロセスです。ほとんどのアプリケーションではこのレベルでの制御は不要です。開発者は、KeyboardFocusManager を全体的に置き換えるという手段をとる前に、このドキュメントで説明する KeyEventPostProcessor、FocusTraversalPolicy、VetoableChangeListener、およびそのほかの概念を使用することが推奨されます。

制約を受けることなくほかのコンテキスト内の Component にアクセスできるということはセキュリティーホールを意味するため、SecurityManager は、クライアントコードが KeyboardFocusManager を任意のサブクラスのインスタンスに置き換えることを許可する前に、新しいアクセス権「replaceKeyboardFocusManager」を付与する必要があります。セキュリティーチェックのため、ブラウザ内のアプレットなど、SecurityManager が存在する環境に配置されるアプリケーションでは、KeyboardFocusManager を置き換えるというオプションはありません。

KeyboardFocusManager インスタンスは、インストールされると、protected の関数のセットを介してグローバルフォーカス状態にアクセスできます。KeyboardFocusManager は、呼び出し元スレッドのコンテキスト内にインストールされている場合にかぎってこれらの関数を呼び出すことができます。これにより、悪意のあるコードが KeyboardFocusManager.setCurrentFocusManager のセキュリティーチェックを回避できなくなります。KeyboardFocusManager は常に、コンテキストのフォーカス状態ではなくグローバルのフォーカス状態を処理するべきです。そうしないと、KeyboardFocusManager が正しく動作しなくなります。

KeyboardFocusManager の主な責任は、次のイベントをディスパッチすることです。

ピアレイヤーは、KeyboardFocusManager に対して、WINDOW_ACTIVATED および WINDOW_DEACTIVATED 以外のすべての上記イベントを提供します。KeyboardFocusManager は、適切な場合には WINDOW_ACTIVATEDWINDOW_DEACTIVATED イベントを合成し、適切なターゲットに送信する必要があります。

KeyboardFocusManager は、ピアレイヤーによって提供されたイベントのターゲットを、自身の概念によるフォーカス所有者またはフォーカスされた Window に変更する必要がある場合があります。

KeyboardFocusManager は、イベントが適切な順序であること、およびイベントとその反対のイベントタイプとが一対一対応であることを保証する必要があります。ピアレイヤーは、これらを一切保証しません。たとえば、ピアレイヤーが WINDOW_GAINED_FOCUS イベントの前に FOCUS_GAINED イベントを送信する可能性があります。WINDOW_GAINED_FOCUS イベントが FOCUS_GAINED イベントの前にディスパッチされることを保証することは、KeyboardFocusManager の責任です。

KeyboardFocusManager.redispatchEvent を介してイベントを再ディスパッチする前に、KeyboardFocusManager はグローバルフォーカス状態の更新を試みる必要があります。通常、これは KeyboardFocusManager.setGlobal* メソッドのいずれかを使用して行われますが、実装は、独自のメソッドを実装することもできます。KeyboardFocusManager は、更新を試みたあとで、グローバルフォーカス状態の変更が拒否されなかったことを確認する必要があります。対応する getGlobal* メソッドの呼び出しが、たった今設定した値と異なる値を返したときに、拒否されたことが検知されます。次の 3 つの標準的な場合に拒否が発生します。

KeyboardFocusManager のクライアント定義の実装は、拒否されるフォーカス移動のセットを、グローバルフォーカス状態に対するアクセス用メソッドおよび変更用メソッドをオーバーライドすることによって調整できます。

グローバルフォーカス状態の変更リクエストが拒否された場合、KeyboardFocusManager はフォーカス変更リクエストを要求したイベントを破棄する必要があります。イベントのターゲットであった Component がこのイベントを受け取ってはいけません。

KeyboardFocusManager は、フォーカスと VetoableChangeListener で概説されているように、拒否回復を開始することも要求されます。

最後に、KeyboardFocusManager は次のような特殊ケースを処理する必要があります。

以前のリリースとの非互換性

クロスプラットフォームの変更:

  1. すべての Component の、デフォルトのフォーカストラバーサル可能性は「true」になりました。以前は、一部の Component (特にすべての軽量 Component) のデフォルトのフォーカストラバーサル可能性は「false」でした。ただし、この変更にかかわらず、すべての AWT Container の DefaultFocusTraversalPolicy は、以前のリリースのトラバーサル順序を維持します。
  2. フォーカストラバーサル不可能な (つまりフォーカス不可能な) Component にフォーカスするリクエストは拒否されます。以前は、このようなリクエストは許可されていました。
  3. Window.toFront() および Window.toBack() は、Window が不可視の場合は何も実行しなくなりました。以前は、動作はプラットフォーム依存でした。
  4. Component にインストールされた KeyListener は、フォーカストラバーサル操作にマッピングされる KeyEvent を認識しなくなり、このようなイベントに対して Component.handleEvent() は呼び出されなくなりました。以前は、AWT Component はこれらのイベントを認識し、AWT がフォーカストラバーサルを開始する前にイベントを消費する機会がありました。代わりに、この機能を必要とするコードは、その Component のフォーカストラバーサルキーを無効にし、フォーカストラバーサル自体を処理するようにしてください。あるいは、AWTEventListener または KeyEventDispatcher を使用して、すべての KeyEvent を事前待機することもできます。

Microsoft Windows 固有の変更:

  1. Z 軸順の変更後、Window.toBack() はフォーカスされた Window を最前面の Window に変更します。
  2. requestFocus() は、すべての場合に Window 間のフォーカス変更リクエストを許可するようになりました。以前は、リクエストは重量 Component に関しては許可されていましたが、軽量 Component に関しては拒否されていました。