概要

JTabbedPaneのカーソルキーによるタブ選択遷移を変更してループ不可、またはタブにフォーカスがない場合でも移動可能に設定します。

サンプルコード

InputMap im0 = tabs.getInputMap(JComponent.WHEN_FOCUSED);
InputMap im1 = tabs.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
ActionMap am = tabs.getActionMap();

String prev = "navigatePrevious";
am.put(prev, new TabNavigateAction(tabs, am.get(prev)));
im0.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), prev);
im1.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK), prev);
im0.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), prev);
im1.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK), prev);

String next = "navigateNext";
am.put(next, new TabNavigateAction(tabs, am.get(next)));
im0.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), next);
im1.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK), next);
im0.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), next);
im1.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK), next);
// ...
class TabNavigateAction extends AbstractAction {
  private final JTabbedPane tabs;
  private final transient Action action;

  protected TabNavigateAction(JTabbedPane tabbedPane, Action action) {
    super();
    this.tabs = tabbedPane;
    this.action = action;
  }

  @Override public void actionPerformed(ActionEvent e) {
    if (action != null && action.isEnabled()) {
      boolean isWrap = tabs.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT;
      boolean isAltDown = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
      Object name = action.getValue(Action.NAME);
      int base = tabs.getSelectedIndex();
      boolean prev = Objects.equals(name, "navigatePrevious") && base != 0;
      boolean next = Objects.equals(name, "navigateNext") && base != tabs.getTabCount() - 1;
      if (isWrap || isAltDown || prev || next) {
        action.actionPerformed(new ActionEvent(tabs,
            ActionEvent.ACTION_PERFORMED, null,
            e.getWhen(), e.getModifiers()));
      }
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • タブ自体にフォーカスが存在し、かつタブレイアウトがJTabbedPane.SCROLL_TAB_LAYOUTの場合:
    • キーにループ不可に設定したnavigatePreviousアクションを割り当て
    • キーにループ不可に設定したnavigateNextアクションを割り当て
  • タブがフォーカスコンポーネントの祖先(タブ自体にフォーカスが存在する場合も含む)の場合:
    • Alt + ←Alt + ↑キーにデフォルトのnavigatePreviousアクションを割り当て
    • Alt + →Alt + ↓キーにデフォルトのnavigateNextアクションを割り当て

参考リンク

コメント