概要

FocusTraversalPolicyを使用してフォーカスをもつコンポーネントを取得し、その全体が表示されるまでスクロールします。

サンプルコード

Box box = Box.createVerticalBox();
box.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
IntStream.range(0, 20).forEach(i -> {
  box.add(new JTextField("test" + i));
  box.add(Box.createVerticalStrut(5));
});
box.add(Box.createVerticalGlue());
box.setFocusCycleRoot(true);
box.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
  @Override public Component getComponentAfter(
        Container focusCycleRoot, Component aComponent) {
    Component c = super.getComponentAfter(focusCycleRoot, aComponent);
    if (focusCycleRoot instanceof JComponent) {
      ((JComponent) focusCycleRoot).scrollRectToVisible(c.getBounds());
    }
    return c;
  }

  @Override public Component getComponentBefore(
        Container focusCycleRoot, Component aComponent) {
    Component c = super.getComponentBefore(focusCycleRoot, aComponent);
    if (focusCycleRoot instanceof JComponent) {
      ((JComponent) focusCycleRoot).scrollRectToVisible(c.getBounds());
    }
    return c;
  }
});
add(new JScrollPane(box));
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、JScrollPane内に配置されているコンポーネントにフォーカスが移動した場合、そのコンポーネント全体が表示されるようにスクロールを行うFocusTraversalPolicyを作成しています。

  • 左: Default
    • 表示範囲外にあるJTextFieldTabキーなどでフォーカスが移動しても自動的にスクロールしない
  • 右: LayoutFocusTraversalPolicy#getComponentAfter(...)
    • LayoutFocusTraversalPolicy#getComponentAfter(...)メソッドなどをオーバーライドしてフォーカスを取得するコンポーネントを取得し、JComponent#scrollRectToVisible(...)メソッドでそのコンポーネントの領域が表示されるまでスクロールを実行

参考リンク

コメント