TITLE:Focusの移動
#navi(../)
#tags(FocusTraversalPolicy, Focus)
RIGHT:Posted by &author(aterai); at 2004-04-26
*Focusの移動 [#x8547c84]
``FocusTraversalPolicy``を使って、KBD{TAB}キーなどによるフォーカスの移動を制御します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTNE9BAwqI/AAAAAAAAAaM/57d2rzX7ixk/s800/FocusTraversal.png)

**サンプルコード [#le272dee]
#code(link){{
final JButton nb = new JButton("NORTH");
final JButton sb = new JButton("SOUTH");
final JButton wb = new JButton("WEST");
final JButton eb = new JButton("EAST");
add(new JScrollPane(textarea));
add(nb, BorderLayout.NORTH);
add(sb, BorderLayout.SOUTH);
add(wb, BorderLayout.WEST);
add(eb, BorderLayout.EAST);
FocusTraversalPolicy policy = new FocusTraversalPolicy() {
  //private final List<Component> order = Arrays.asList(
  //    new Component[] {eb, wb, sb, nb});
  private final List<? extends Component> order = Arrays.asList(eb, wb, sb, nb);
  @Override public Component getFirstComponent(Container focusCycleRoot) {
    return order.get(0);
  }
  @Override public Component getLastComponent(Container focusCycleRoot) {
    return order.get(order.size()-1);
  }
  @Override public Component getComponentAfter(
      Container focusCycleRoot, Component aComponent) {
    int i = order.indexOf(aComponent);
    return order.get((i + 1) % order.size());
  }
  @Override public Component getComponentBefore(
      Container focusCycleRoot, Component aComponent) {
    int i = order.indexOf(aComponent);
    return order.get((i - 1 + order.size()) % order.size());
  }
  @Override public Component getDefaultComponent(Container focusCycleRoot) {
    return order.get(0);
  }
};
frame.setFocusTraversalPolicy(policy);
//setFocusTraversalPolicyProvider(true);
//setFocusTraversalPolicy(policy);
}}

**解説 [#h3d0848b]
上記のサンプルでは、``FocusTraversalPolicy``を使用することで、キー入力によるフォーカスの移動を制御しています。また、ラジオボタンで以下のような``FocusTraversalPolicy``に切り替えることができます。

- ``Default``
-- ``JPanel``のデフォルトは、``null``
-- 実際のキー入力によるフォーカスの移動には、このパネルの親(``JFrame``)に設定されている``FocusTraversalPolicy``が使用される

- ``Custom``
-- [http://www.ibm.com/developerworks/jp/java/library/j-mer07153/ Merlinの魔術: フォーカス、フォーカス、フォーカス]からの引用
-- KBD{TAB}キーを押していくと、東西南北の順でボタンのフォーカスが移動(KBD{Shift}+KBD{TAB}キーでは逆順)
-- ``4``つの``JButton``以外には、KBD{TAB}キーでフォーカスは移動しない

- ``Layout``
-- 以下のように``LayoutFocusTraversalPolicy``(``LayoutFocusTraversalPolicy``は``Swing``のデフォルト、``AWT``のデフォルトは``DefaultFocusTraversalPolicy``)の``accept``メソッドをオーバーライドして、中央の``JTextArea``(通常、``JTextArea``などから次のコンポーネントにフォーカス移動する場合は、KBD{Ctrl}+KBD{TAB})が編集不可の場合は、これにKBD{TAB}キーなどでフォースが移動しないように設定している

#code{{
frame.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
  @Override protected boolean accept(Component c) {
    if(c instanceof JTextComponent && !((JTextComponent)c).isEditable()) {
      return false;
    }else{
      return super.accept(c);
    }
    //return (c==textarea)?false:super.accept(c);
  }
});
}}

**参考リンク [#n149aa1a]
- [http://docs.oracle.com/javase/jp/6/api/java/awt/doc-files/FocusSpec.html The AWT Focus Subsystem]
- [http://www.ibm.com/developerworks/jp/java/library/j-mer07153/ Merlinの魔術: フォーカス、フォーカス、フォーカス]
- [[Windowを開いたときのフォーカスを指定>Swing/DefaultFocus]]
- [[FocusTraversalKeysに矢印キーを追加してフォーカス移動>Swing/FocusTraversalKeys]]

**コメント [#o2ee0e2b]
#comment