概要

JTabbedPaneのスクロールタブレイアウトで矢印ボタンにCtrlキーを押しながらクリックすると先頭もしくは末尾のタブまでスクロールするアクションを追加します。

サンプルコード

class ScrollTabsAction extends AbstractAction {
  private final JTabbedPane tabbedPane;
  private final Action action;
  private final int index;

  protected ScrollTabsAction(JTabbedPane tabbedPane, Action action) {
    super();
    this.tabbedPane = tabbedPane;
    this.action = action;
    Object name = action.getValue(Action.NAME);
    String forward = "scrollTabsForwardAction";
    this.index = Objects.equals(name, forward) ? tabbedPane.getTabCount() - 1 : 0;
  }

  @Override public void actionPerformed(ActionEvent e) {
    if (action != null && action.isEnabled()) {
      boolean isCtrlDown = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
      if (isCtrlDown) {
        scrollTabAt(tabbedPane, index);
      } else {
        action.actionPerformed(new ActionEvent(tabbedPane,
            ActionEvent.ACTION_PERFORMED, null,
            e.getWhen(), e.getModifiers()));
      }
    }
  }

  public static void scrollTabAt(JTabbedPane tabbedPane, int index) {
    Component cmp = null;
    for (Component c : tabbedPane.getComponents()) {
      if ("TabbedPane.scrollableViewport".equals(c.getName())) {
        cmp = c;
        break;
      }
    }
    if (cmp instanceof JViewport) {
      JViewport viewport = (JViewport) cmp;
      Dimension d = tabbedPane.getSize();
      Rectangle r = tabbedPane.getBoundsAt(index);
      int gw = (d.width - r.width) / 2;
      r.grow(gw, 0);
      viewport.scrollRectToVisible(r);
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • scrollTabsForwardAction
    • JTabbedPane.getActionMap().get("scrollTabsForwardAction")でアクションを取得
    • AbstractAction#actionPerformed(...)をオーバーライドしてCtrlキーが押されている(ActionEvent#getModifiers() & ActionEvent.CTRL_MASK) != 0場合は、末尾タブtabbedPane.getTabCount() - 1までスクロール、それ以外は先に取得したscrollTabsForwardActionを実行するよう設定
    • JTabbedPane.getActionMap().put("scrollTabsForwardAction", action)でアクションを置換
  • scrollTabsBackwardAction
    • JTabbedPane.getActionMap().get("scrollTabsBackwardAction")でアクションを取得
    • AbstractAction#actionPerformed(...)をオーバーライドしてCtrlキーが押されている(ActionEvent#getModifiers() & ActionEvent.CTRL_MASK) != 0場合は、先頭タブ0までスクロール、それ以外は先に取得したscrollTabsBackwardActionを実行するよう設定
    • JTabbedPane.getActionMap().put("scrollTabsBackwardAction", action)でアクションを置換

  • scrollTabsForwardActionscrollTabsBackwardActionはスクロールするだけなので、このサンプルで置換したアクションでも先頭末尾へのスクロールのみ実行してタブの選択状態は変化しない

参考リンク

コメント