概要

JComboBoxのエディタなどに内余白を設定します。

サンプルコード

static Border padding = BorderFactory.createEmptyBorder(0, 5, 0, 0);
//...
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
model.addElement("aaaaaaaaaaaaaaaaaaaaaaaaa");
model.addElement("aaaabbb");
model.addElement("aaaabbbcc");
model.addElement("bbb1");
model.addElement("bbb12");

JComboBox<String> combo = new JComboBox<String>(model) {
  @Override public void updateUI() {
    setRenderer(null);
    super.updateUI();
    final ListCellRenderer<? super String> lcr = getRenderer();
    setRenderer(new ListCellRenderer<String>() {
      @Override public Component getListCellRendererComponent(
          JList<? extends String> list, String value, int index,
          boolean isSelected, boolean hasFocus) {
        JLabel l = (JLabel) lcr.getListCellRendererComponent(
            list, value, index, isSelected, hasFocus);
        l.setBorder(padding);
        return l;
      }
    });
    //XXX JDK 1.7.0 ?: ((JLabel) lcr).setBorder(padding);
  }
};
view all

解説

上記のサンプルでは、JComboBoxに、Border(EmptyBorderMatteBorderを切り替え可能)を設定したListCellRendererを設定して、ドロップダウンリストの左余白をすこし広げています。JComboBoxが編集不可の場合、エディタ部分もこの余白が自動的に適用されます。

  • 0:編集不可
    • ListCellRendererで余白を指定

以下は、JComboBoxが編集可の場合のテストです。

  • 1: テキストフィールドの元Border + 任意のBorderで余白を設定
    • editor.setBorder(BorderFactory.createCompoundBorder(editor.getBorder(), padding));
    • JComboBox#getEditor()#getEditorComponent()で取得したJTextFieldに余白を指定
    • JDK 1.5では余白を指定しても反映されない
    • JDK 1.6では取得したJTextFieldをsetOpaque(true)としないと背景色は反映されない
  • 2: テキストフィールドの元Borderは無視して任意のBorderのみで余白を設定
    • editor.setBorder(padding);
    • JComboBox#getEditor()#getEditorComponent()で取得したJTextFieldに余白を指定
    • MetalLookAndFeelでテキストフィールドの枠が描画できない

  • 3: テキストフィールドのInsets + 5ピクセル余白を設定
    • editor.setMargin(new Insets(i.top,i.left+5,i.bottom,i.right));
    • MetalLookAndFeel, MotifLookAndFeel, WindowsLookAndFeelなどでは無効
    • NimbusLookAndFeelでは有効だが、JComboBoxの高さなども変化してしまう
  • 4: テキストフィールドのMargin + 5ピクセル余白を設定
    • editor.setMargin(new Insets(m.top,m.left+5,m.bottom,m.right));
    • MetalLookAndFeel, MotifLookAndFeel, WindowsLookAndFeelなどでは無効
    • NimbusLookAndFeelでは有効

  • 5: JComboBoxBorder + 任意のBorderで余白をJComboBox自身に設定
    • JComboBox#setBorder()で、元のBorderの内側に余白を指定
    • WindowsLookAndFeel, MotifLookAndFeelで有効?
    • MetalLookAndFeel, NimbusLookAndFeelでは、JComboBoxの外側に余白が付く
  • 6: JComboBoxBorder + 任意のBorderで余白をJComboBox自身に設定
    • JComboBox#setBorder()で、元のBorderの外側に余白を指定
    • WindowsLookAndFeelで余計な枠が表示される?

その他にも、以下のようにUIManagerで余白を設定する方法もありますが、LookAndFeelによって対応が異なる?ようです。 ComboBox.paddingは無くなっている?

JComboBoxが編集可能の場合は、ComboBox.editorBorderが有効かもしれない。

//UIManager.put("ComboBox.padding", new InsetsUIResource(insets));
UIManager.put("ComboBox.editorBorder", BorderFactory.createEmptyBorder(0, 5, 0, 0));

上記のサンプルを、余白に色無しにして、Ubuntu 7.04(GNOME 2.18.1)、JDK 1.6.0で実行すると、以下のようになります。

PaddingComboBox1.png

  • LookAndFeel毎にJComboBoxの余白の描画は異なるみたいなので、全部まとめて消すのは難しい?
  • BasicComboBoxUIも、ComboBox.buttonDarkShadowArrowButtonの三角とボタンの影に使われていて微妙
    • BasicComboBoxUI#createArrowButton()をオーバーライドして別途三角形アイコンを使う方がよさそう

コードは、JComboBoxのBorderを変更するに移動。

参考リンク

コメント

  • なんだか、よく分からなくなってきましたorz。 JDK 1.6.0_10-beta-b22で、BasicComboBoxUIpaddingにすこし修正が入っている?ようです。 -- aterai
  • LookAndFeelの切り替えなどを追加しました。 -- aterai
  • 1.7.0_06NimbusなどのComboBox.popupInsetsが修正? Bug ID: 7158712 Synth Property "ComboBox.popupInsets" is ignored -- aterai
  • Windows 7LookAndFeel、編集不可のJComboBoxで、( (JLabel) combo.getRenderer() ).setBorder(padding);JComboBox本体に効かない(フォーカスのためのBorderのせい?)ため、セルレンダラーを作成して毎回余白を適用するように変更。このため、Windows 7LookAndFeelでは、JComboBox本体の点線によるフォーカス表示が無くなる。 -- aterai