概要

JTabbedPaneで現在選択されているタブとその直前に選択されていたタブのフォーカスBorderの色を変更します。

スクリーンショット

Swing/PreviouslySelectedTabColor.png

サンプルコード

class LineFocusTabbedPane extends JTabbedPane {
  private transient ChangeListener listener;

  protected LineFocusTabbedPane() {
    super();
  }

  @Override public void updateUI() {
    removeChangeListener(listener);
    UIManager.put("TabbedPane.tabInsets", new InsetsUIResource(1, 4, 0, 4));
    UIManager.put("TabbedPane.selectedTabPadInsets", new InsetsUIResource(1, 1, 1, 1));
    UIManager.put("TabbedPane.tabAreaInsets", new InsetsUIResource(3, 2, 0, 2));
    UIManager.put("TabbedPane.selectedLabelShift", 0);
    UIManager.put("TabbedPane.labelShift", 0);
    UIManager.put("TabbedPane.focus", new ColorUIResource(new Color(0x0, true)));
    super.updateUI();
    listener = new TabSelectionListener();
    addChangeListener(listener);
    setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
  }

  @Override public void insertTab(String title, Icon icon, Component c, String tip, int index) {
    super.insertTab(title, icon, c, tip, index);
    JLabel label = new JLabel(title, icon, SwingConstants.CENTER);
    setTabComponentAt(index, label);
  }
}

class TabSelectionListener implements ChangeListener {
  private static final Color ALPHA_ZERO = new Color(0x0, true);
  private static final Color SELECTION_COLOR = new Color(0x00_AA_FF);
  private static final Color PREV_COLOR = new Color(0x48_00_AA_FF, true);
  private int prev = -1;

  @Override public void stateChanged(ChangeEvent e) {
    JTabbedPane tabbedPane = (JTabbedPane) e.getSource();
    if (tabbedPane.getTabCount() <= 0) {
      return;
    }
    int idx = tabbedPane.getSelectedIndex();
    for (int i = 0; i < tabbedPane.getTabCount(); i++) {
      Component tab = tabbedPane.getTabComponentAt(i);
      if (tab instanceof JComponent) {
        Color color;
        if (i == idx) {
          color = SELECTION_COLOR;
        } else if (i == prev) {
          color = PREV_COLOR;
        } else {
          color = ALPHA_ZERO;
        }
        ((JComponent) tab).setBorder(BorderFactory.createMatteBorder(3, 0, 0, 0, color));
      }
    }
    prev = idx;
  }
}
View in GitHub: Java, Kotlin

解説

  • JTabbedPaneのタブが選択されている場合のフォーカスBorderを下線に変更するで使用したJTabbedPane同様選択されたタブのフォーカスBorderMatteBorderで表示するよう変更
    • デフォルトの点線のフォーカスBorderUIManager.put("TabbedPane.focus", new ColorUIResource(new Color(0x0, true)))で非表示化
  • JTabbedPaneChangeListenerを追加して直前に選択されていたタブのインデックスを記憶し、タブ選択が変更されたらすべてのタブのフォーカスBorderを更新
    • 直前に選択されていたタブのフォーカスBorder色は現在選択されているタブのフォーカスBorder色よりアルファ値を下げて残像風に薄く表示
    • JTabbedPaneで現在のタブを閉じた後に選択されるタブを変更するのように選択タブの履歴をArrayListなどに記憶しておけば直前だけでなく2つ前、3つ前などのタブのフォーカスBorder色を変更することも可能

参考リンク

コメント