• category: swing folder: ComboBoxSelectionBackground title: JComboBoxのドロップダウンリストでの選択背景色を変更する tags: [JComboBox, JList, UIManager] author: aterai pubdate: 2017-09-18T18:34:08+09:00 description: JComboBoxのドロップダウンリストで使用されるJListの選択背景色と選択文字色を変更します。 image: https://drive.google.com/uc?id=1j4KzCS-He6w9JuyRopBvRfEgr3S-XgXxrA

概要

JComboBoxのドロップダウンリストで使用されるJListの選択背景色と選択文字色を変更します。

サンプルコード

UIManager.put("ComboBox.selectionBackground", Color.PINK);
UIManager.put("ComboBox.selectionForeground", Color.CYAN);

String[] model = {"111", "2222", "33333"};

JComboBox<String> combo0 = new JComboBox<>(model);

JComboBox<String> combo1 = new JComboBox<String>(model) {
  @Override public void updateUI() {
    super.updateUI();
    Object o = getAccessibleContext().getAccessibleChild(0);
    if (o instanceof ComboPopup) {
      JList list = ((ComboPopup) o).getList();
      list.setSelectionForeground(Color.WHITE);
      list.setSelectionBackground(Color.ORANGE);
    }
  }
};

JComboBox<String> combo2 = new JComboBox<String>(model) {
  @Override public void updateUI() {
    super.updateUI();
    setRenderer(new DefaultListCellRenderer() {
      @Override public Component getListCellRendererComponent(
          JList list, Object value, int index,
          boolean isSelected, boolean hasFocus) {
        JLabel l = (JLabel) super.getListCellRendererComponent(
            list, value, index, isSelected, hasFocus);
        if (isSelected) {
          l.setForeground(Color.WHITE);
          l.setBackground(Color.ORANGE);
        } else {
          l.setForeground(Color.BLACK);
          l.setBackground(Color.WHITE);
        }
        return l;
      }
    });
  }
};
View in GitHub: Java, Kotlin

解説

  • UIManager.put(ComboBox.selection*, ...)
    • UIManager.put("ComboBox.selectionBackground", bgc);UIManager.put("ComboBox.selectionForeground", fgc);を使用してJListの選択背景色と選択文字色を変更
    • ドロップダウンリストで使用されるJListのみが対象
    • LookAndFeelに依存し、例えばNimbusLookAndFeelではどちらの指定も無効
  • ComboPopup.getList().setSelection*(...)
    • JComboBox#getAccessibleContext()#getAccessibleChild(0)ComboPopupを取得
    • ComboPopup#getList()メソッドでドロップダウンリストで使用されるJListを取得
    • JList#setSelectionForeground(...)JList#setSelectionBackground(...)メソッドを使用してその選択背景色と選択文字色を変更
    • MetalLookAndFeelで編集不可のJComboBoxの場合、JComboBox本体の選択背景色も変更される
  • DefaultListCellRenderer
    • 参考: JComboBoxの文字色を変更する
    • DefaultListCellRenderer#getListCellRendererComponent(...)メソッドをオーバーライドして選択背景色と選択文字色を変更
    • MetalLookAndFeelで編集不可のJComboBoxの場合、JComboBox本体の選択背景色は変更されない
      • このサンプルの場合、ドロップダウンリストの選択背景色に設定したオレンジ色ではなくUIManager.put("ComboBox.selectionBackground", Color.PINK)で設定したピンク色になる
    • JComboBox本体のフォーカス時のBorder(WindowsLookAndFeelの場合はWindowsBorders.DashedBorder)が非表示になる
      • 回避方法: セルの描画をDefaultListCellRendererを継承するレンダラーではなく、JComboBox#getRenderer()で取得したLookAndFeelのデフォルトセルレンダラーに移譲するなどの方法がある
        JComboBox<String> combo3 = new JComboBox<String>(model) {
          @Override public void updateUI() {
            setRenderer(null);
            super.updateUI();
            ListCellRenderer<? super String> defaultRenderer = getRenderer();
            setRenderer(new ListCellRenderer<String>() {
              @Override public Component getListCellRendererComponent(
                  JList<? extends String> list, String value, int index,
                  boolean isSelected, boolean hasFocus) {
                JLabel l = (JLabel) defaultRenderer.getListCellRendererComponent(
                    list, value, index, isSelected, hasFocus);
                if (isSelected) {
                  l.setForeground(Color.WHITE);
                  l.setBackground(Color.ORANGE);
                } else {
                  l.setForeground(Color.BLACK);
                  l.setBackground(Color.WHITE);
                }
                return l;
              }
            });
          }
        };
        

参考リンク

コメント