概要

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 all

解説

  • 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(...)メソッドを使用してその選択背景色と選択文字色を変更
  • DefaultListCellRenderer
    • 参考: JComboBoxの文字色を変更する
    • DefaultListCellRenderer#getListCellRendererComponent(...)メソッドをオーバーライドして選択背景色と選択文字色を変更
    • 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;
              }
            });
          }
        };
        

参考リンク

コメント