Swing/ContainerOrderFocusTraversalPolicy の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/ContainerOrderFocusTraversalPolicy へ行く。
- Swing/ContainerOrderFocusTraversalPolicy の差分を削除
--- 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