---
category: swing
folder: ContainerOrderFocusTraversalPolicy
title: ComponentのFocus移動をContainerに追加した順番に設定する
tags: [Container, Component, Focus, FocusTraversalPolicy, LayoutManager]
author: aterai
pubdate: 2024-01-01T12:39:23+09:00
description: ComponentのFocus移動を親Containerに追加した順番で循環するContainerOrderFocusTraversalPolicyを設定します。
image: https://drive.google.com/uc?id=1lG6lBzr-HmSWdfylbxnJpFOe7x-0HfBZ
---
* 概要 [#summary]
`Component`の`Focus`移動を親`Container`に追加した順番で循環する`ContainerOrderFocusTraversalPolicy`を設定します。

#download(https://drive.google.com/uc?id=1lG6lBzr-HmSWdfylbxnJpFOe7x-0HfBZ)

* サンプルコード [#sourcecode]
#code(link){{
JPanel p = new JPanel(new GridBagLayout());
p.setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy());
p.setFocusTraversalPolicyProvider(true);
p.setFocusable(false);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 1;
List<JComponent> list = Arrays.asList(
    new JRadioButton("JRadioButton1"),
    new JRadioButton("JRadioButton2"),
    new JRadioButton("JRadioButton3", true),
    new JLabel("JLabel1"),
    new JLabel("JLabel2"),
    new JCheckBox("JCheckBox1"),
    new JCheckBox("JCheckBox2"));
for (JComponent c : list) {
  if (c instanceof JRadioButton) {
    group.add((JRadioButton) c);
  } else if (c instanceof JLabel) {
    c.setFocusable(false);
  }
  p.add(c, gbc);
}
gbc.gridx = 2;
gbc.weightx = 1.0;
list.forEach(c -> p.add(new JTextField(), gbc));
}}

* 解説 [#explanation]
- `LayoutFocusTraversalPolicy`
-- `Swing`の軽量コンポーネントのデフォルト
--- `ContainerOrderFocusTraversalPolicy`を継承する`DefaultFocusTraversalPolicy`は`AWT`の重量コンポーネント用のデフォルト
--- `DefaultFocusTraversalPolicy#accept(...)`をオーバーライドして軽量コンポーネントは拒否するので、`JPanel`などの軽量コンポーネントに`DefaultFocusTraversalPolicy`を設定するとタブキーによる子コンポーネントのフォーカス移動が不可になる
-- 追加順ではなくレイアウトされた座標などに従って(`SortingFocusTraversalPolicy`や`LayoutComparator`を参照)フォーカス移動するため、たとえばこのサンプルの`JRadioButton`の次のフォーカスは右隣の`JTextField`になる
- `ContainerOrderFocusTraversalPolicy`
-- コンポーネントの追加順(`Container#getComponentZOrder(...)`で取得可能な`Z`軸順インデックス)でフォーカス移動する`FocusTraversalPolicy`
-- たとえばこのサンプルの`JRadioButton`の次のフォーカスは`JCheckBox`になる
--- タブキーによるフォーカス移動で`JRadioButton`の次が`JRadioButton`にならないのは、同一`ButtonGroup`内のボタンはスキップするよう`BasicButtonUI`で設定されているため
--- `LayoutFocusTraversalPolicy`では`JLabel`のような`JComponent.WHEN_FOCUSED`時の`InputMap`が存在しないコンポーネントは自動的にフォーカス移動対象外となるが、`ContainerOrderFocusTraversalPolicy`はそうではないので、このサンプルの`JLabel`には`setFocusable(false)`を設定することでフォーカス移動の対象から除外している
- `ContainerOrderFocusTraversalPolicy` + `ButtonGroupFocusTraversalPolicy`
-- [[ButtonGroup内で最初にフォーカスを取得するJRadioButtonを変更する>Swing/ButtonGroupFocusTraversalPolicy]]同様、`ContainerOrderFocusTraversalPolicy#getDefaultComponent(...)`をオーバーライドして選択状態の`JRadioButton`に初期フォーカスを設定

* 参考リンク [#reference]
- [[Focusの移動>Swing/FocusTraversal]]
- [AWTフォーカス・サブシステム](https://docs.oracle.com/javase/jp/8/docs/api/java/awt/doc-files/FocusSpec.html)
- [https://docs.oracle.com/javase/jp/8/docs/api/java/awt/doc-files/FocusSpec.html AWTフォーカス・サブシステム]
- [[JRadioButtonの選択アイコンを除いたテキスト先頭をJLabelと揃える>Swing/RadioButtonsLabelAlignment]]
-- `JColorChooser`の色選択パネルに`ContainerOrderFocusTraversalPolicy`が使用されている
- [[ButtonGroup内で最初にフォーカスを取得するJRadioButtonを変更する>Swing/ButtonGroupFocusTraversalPolicy]]

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