---
category: swing
folder: VariableRoundedBorderOnComboBox
title: JComboBoxのBorderをドロップダウンリストの表示状態で切り替える
tags: [JComboBox, Border, PopupMenuListener]
author: aterai
pubdate: 2024-03-11T02:49:30+09:00
description: JComboBoxのBorderをドロップダウンリストの表示状態で切り替えて左右の辺が直線で描画されるよう設定します。
image: https://drive.google.com/uc?id=1srDCMSHQw2olzIC8t0q1MQjJRHhVR4y_
---
* 概要 [#summary]
`JComboBox`の`Border`をドロップダウンリストの表示状態で切り替えて左右の辺が直線で描画されるよう設定します。

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

* サンプルコード [#sourcecode]
#code(link){{
JComboBox<String> combo1 = new JComboBox<String>(model) {
  private transient PopupMenuListener listener;

  @Override public void updateUI() {
    setRenderer(null);
    removePopupMenuListener(listener);
    super.updateUI();
    setBorder(new RoundedCornerBorder());
    setRenderer(new RoundedCornerListCellRenderer());
    setUI(new BasicComboBoxUI() {
      // ...
    }
    listener = new HeavyWeightContainerListener();
    addPopupMenuListener(listener);
    Object o = getAccessibleContext().getAccessibleChild(0);
    if (o instanceof JComponent) {
      JComponent c = (JComponent) o;
      c.setBorder(new BottomRoundedCornerBorder());
      c.setBackground(Color.WHITE);
    }
  }
};
// ...
class HeavyWeightContainerListener implements PopupMenuListener {
  @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
    EventQueue.invokeLater(() -> {
      JComboBox<?> combo = (JComboBox<?>) e.getSource();
      combo.setBorder(new TopRoundedCornerBorder());
      Accessible a = combo.getUI().getAccessibleChild(combo, 0);
      if (a instanceof JPopupMenu) {
        Window w = SwingUtilities.getWindowAncestor((Component) a);
        if (w != null && w.getType() == Window.Type.POPUP) {
          // Popup$HeavyWeightWindow
          w.setBackground(new Color(0x0, true));
        }
      }
    });
  }

  @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
    JComboBox<?> combo = (JComboBox<?>) e.getSource();
    combo.setBorder(new RoundedCornerBorder());
  }

  @Override public void popupMenuCanceled(PopupMenuEvent e) {
    /* not needed */
  }
}
}}

* 解説 [#explanation]
- `JComboBox`本体には`RoundedCornerBorder`(`4`隅を丸めたラウンド矩形`Border`)を設定
- `BasicComboPopup`(ドロップダウンリスト用)には`BottomRoundedCornerBorder`(左右下の`2`隅を丸めたラウンド矩形`Border`)を設定
- `PopupMenuListener`を`JComboBox`に追加してドロップダウンリストが開いたとき(`PopupMenuListener#popupMenuWillBecomeVisible(...)`)、`JComboBox`本体に`TopRoundedCornerBorder`(左右上の`2`隅を丸めたラウンド矩形`Border`)を設定
-- `JComboBox`本体の左辺とドロップダウンリストの左辺、`JComboBox`本体の右辺とドロップダウンリストの右辺が直線でつながり、本体とドロップダウンリスト全体でひとつの`RoundRectangle2D`を描画する`Border`になる
- ドロップダウンリストが閉じるとき(`PopupMenuListener#popupMenuWillBecomeInvisible(...)`)、`JComboBox`本体の`Border`を`RoundedCornerBorder`に戻す

* 参考リンク [#reference]
- [[JComboBoxのドロップダウンリストに角丸のBorderを設定する>Swing/RoundedDropDownList]]
- [[JComboBoxのドロップダウンリストでアイテム選択状態表示をラウンド矩形に変更する>Swing/RoundedCornerListCellRenderer]]

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