---
category: swing
folder: ComboBoxScrollBar
title: JComboBoxのドロップダウンリストで使用するJScrollBarを変更する
tags: [JComboBox, JScrollBar, JScrollPane, ArrowButton]
author: aterai
pubdate: 2021-03-08T16:39:18+09:00
description: JComboBoxのドロップダウンリストで使用する縦JScrollBarの幅やスタイル、増減ボタンの有無などを変更します。
image: https://drive.google.com/uc?id=1OrhP_jMrcyzy5mrKVnhaw3Qb1iH_mttw
---
* 概要 [#summary]
`JComboBox`のドロップダウンリストで使用する縦`JScrollBar`の幅やスタイル、増減ボタンの有無などを変更します。

#download(https://drive.google.com/uc?id=1OrhP_jMrcyzy5mrKVnhaw3Qb1iH_mttw)

* サンプルコード [#sourcecode]
#code(link){{
JComboBox<String> combo2 = new JComboBox<String>(makeModel()) {
  @Override public void updateUI() {
    UIManager.put(KEY, BorderFactory.createLineBorder(Color.GRAY));
    UIManager.put("ScrollBar.width", 10);
    UIManager.put("ScrollBar.thumbHeight", 20);
    UIManager.put("ScrollBar.minimumThumbSize", new Dimension(30, 30));
    UIManager.put("ScrollBar.incrementButtonGap", 0);
    UIManager.put("ScrollBar.decrementButtonGap", 0);
    UIManager.put("ScrollBar.thumb", THUMB);
    UIManager.put("ScrollBar.track", BACKGROUND);

    UIManager.put("ComboBox.foreground", FOREGROUND);
    UIManager.put("ComboBox.background", BACKGROUND);
    UIManager.put("ComboBox.selectionForeground", SELECTION_FOREGROUND);
    UIManager.put("ComboBox.selectionBackground", BACKGROUND);
    UIManager.put("ComboBox.buttonDarkShadow", BACKGROUND);
    UIManager.put("ComboBox.buttonBackground", FOREGROUND);
    UIManager.put("ComboBox.buttonHighlight", FOREGROUND);
    UIManager.put("ComboBox.buttonShadow", FOREGROUND);

    super.updateUI();
    setUI(new BasicComboBoxUI() {
      @Override protected JButton createArrowButton() {
        JButton b = new JButton(new ArrowIcon(BACKGROUND, FOREGROUND));
        b.setContentAreaFilled(false);
        b.setFocusPainted(false);
        b.setBorder(BorderFactory.createEmptyBorder());
        return b;
      }

      @Override protected ComboPopup createPopup() {
        return new BasicComboPopup(comboBox) {
          @Override protected JScrollPane createScroller() {
            JScrollPane sp = new JScrollPane(list) {
              @Override public void updateUI() {
                super.updateUI();
                getVerticalScrollBar().setUI(new WithoutArrowButtonScrollBarUI());
                getHorizontalScrollBar().setUI(new WithoutArrowButtonScrollBarUI());
              }
            };
            sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)
            sp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER)
            sp.setHorizontalScrollBar(null);
            return sp;
          }
        };
      }
    });
    Object o = getAccessibleContext().getAccessibleChild(0);
    if (o instanceof JComponent) {
      JComponent c = (JComponent) o;
      c.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.GRAY));
      c.setForeground(FOREGROUND);
      c.setBackground(BACKGROUND);
    }
  }
};

// ...
class ZeroSizeButton extends JButton {
  @Override public Dimension getPreferredSize() {
    return new Dimension();
  }
}

class WithoutArrowButtonScrollBarUI extends BasicScrollBarUI {
  @Override protected JButton createDecreaseButton(int orientation) {
    return new ZeroSizeButton();
  }

  @Override protected JButton createIncreaseButton(int orientation) {
    return new ZeroSizeButton();
  }

  @Override protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(trackColor);
    g2.fill(r);
    g2.dispose();
  }

  @Override protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
    JScrollBar sb = (JScrollBar) c;
    if (!sb.isEnabled()) {
      return;
    }
    BoundedRangeModel m = sb.getModel();
    if (m.getMaximum() - m.getMinimum() - m.getExtent() > 0) {
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      Color color;
      if (isDragging) {
        color = thumbDarkShadowColor.brighter();
      } else if (isThumbRollover()) {
        color = thumbLightShadowColor.brighter();
      } else {
        color = thumbColor;
      }
      g2.setPaint(color);
      g2.fillRect(r.x + 1, r.y + 1, r.width - 2, r.height - 2);
      g2.dispose();
    }
  }
}
}}

* 解説 [#explanation]
- 上: `MetalLookAndFeel`デフォルトの編集不可`JComboBox`
- 下: `BasicComboBoxUI`をオーバーライドしてドロップダウンリストのスタイルなどを変更した編集不可`JComboBox`
-- `BasicComboBoxUI#createPopup()`メソッドをオーバーライドして`BasicComboPopup`を生成、さらにその`BasicComboPopup#createScroller()`メソッドをオーバーライドして`JScrollPane`を生成、縦`JScrollBar`などを取得し以下の`UI`を変更
--- [[JScrollPaneの角を丸める>Swing/RoundedScrollPane]]
-- `JScrollBar`の幅: `UIManager.put("ScrollBar.width", 10);`で変更
--- [[JScrollBar上にマウスカーソルが入ったらその幅を拡張する>Swing/ChangeScrollBarWidthOnHover]]
-- `JScrollBar`の増減ボタン: サイズ`0`の`JButton`を使用
-- `JScrollBar`の増減ボタン: サイズ`0`の`JButton`を使用して非表示化
--- [[JScrollBarのArrowButtonを非表示にする>Swing/ArrowButtonlessScrollBar]]
-- `JScrollBar`のハイライト色、背景色など: `BasicScrollBarUI#paintThumb(...)`をオーバーライドして変更
--- [[ScrollBarの表示を変更>Swing/IconScrollBar]]

* 参考リンク [#reference]
- [[JScrollPaneの角を丸める>Swing/RoundedScrollPane]]
-- 角を丸めるなどのコードを除去して簡素化したサンプルをこの記事に移動
- [[JScrollBar上にマウスカーソルが入ったらその幅を拡張する>Swing/ChangeScrollBarWidthOnHover]]
- [[JScrollBarのArrowButtonを非表示にする>Swing/ArrowButtonlessScrollBar]]
- [[ScrollBarの表示を変更>Swing/IconScrollBar]]

* コメント [#comment]
#comment
#comment