• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JComboBoxの内余白
#navi(../)
RIGHT:Posted by [[aterai]] at 2007-05-28
*JComboBoxの内余白 [#s9f3687d]
JComboBoxのエディタなどに内余白を設定します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh3.ggpht.com/_9Z4BYR88imo/TQTQv1E_b9I/AAAAAAAAAgE/nxvnwwFoDyU/s800/PaddingComboBox.png)

**サンプルコード [#o79d2c4d]
#code{{
Border padding = BorderFactory.createEmptyBorder(0,5,0,0);
ListCellRenderer lcr = combo.getRenderer();
((JLabel)lcr).setBorder(padding);
combo.setRenderer(lcr);
}}

**解説 [#ra0eef84]
上記のサンプルでは、JComboBox に、Border((チェックボックスで、EmptyBorderとMatteBorder切り替えることで、余白などを可視化することができます))を設定した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に余白を指定
-- Metal L&F でテキストフィールドの枠が描画できない

----

-3: テキストフィールドのInsets + 5ピクセル余白を設定
-- editor.setMargin(new Insets(i.top,i.left+5,i.bottom,i.right));
-- Metal, Motif, Windows L&F などでは無効
-- Nimbus L&F では有効だが、JComboBoxの高さなども変化してしまう

-4: テキストフィールドのMargin + 5ピクセル余白を設定
-- editor.setMargin(new Insets(m.top,m.left+5,m.bottom,m.right));
-- Metal, Motif, Windows L&F などでは無効
-- Nimbus L&F では有効

----

-5: JComboBoxのBorder + 任意のBorderで余白をJComboBox自身に設定
-- JComboBox#setBorder()で、元のBorderの内側に余白を指定
-- Windows, Motif L&F で有効?
-- Metal, Nimbus L&F では、JComboBoxの外側に余白が付く

-6: JComboBoxのBorder + 任意のBorderで余白をJComboBox自身に設定
-- JComboBox#setBorder()で、元のBorderの外側に余白を指定
-- Windows L&F で余計な枠が表示される?

----
//以下のようにエディタにMarginを指定しても無視されるようです。
//#code{{
//editor = (JTextField) combo.getEditor().getEditorComponent();
//Insets m = editor.getMargin();
//Insets margin = new Insets(m.top,m.left+10,m.bottom,m.right);
////System.out.println(margin.toString());
//editor.setMargin(margin);
//}}
//-追記
//--無視されるのは、Basic L&F系(Windows L&Fなど)で、Synth L&F系(Nimbus, GTK L&Fなど)では上記の設定は有効になる? 
//--1.6.0_10-beta-b13 では、%%Basic L&F系は%% どちらも、UIManager.put("ComboBox.padding", insets) が使用できる?

その他にも、以下のように余白を設定する方法もありますが、L&F によって対応が異なるようです。
#code{{
UIManager.put("ComboBox.padding", new InsetsUIResource(insets));
}}

----
上記のサンプルを、余白に色無しにして、Ubuntu 7.04(GNOME 2.18.1) JDK 1.6.0 で実行すると、以下のようになります。
//#screenshot(,screenshot1.png)
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTQyV_2TnI/AAAAAAAAAgI/yqGoi_zqsgI/s800/PaddingComboBox1.png)

----
- Look&Feel毎にJComboBoxの余白の描画は異なるみたいなので、全部まとめて消すのは難しい?
- BasicComboBoxUI も、ComboBox.buttonDarkShadow がArrowButtonの三角とボタンの影に使われていて微妙
-- BasicComboBoxUI#createArrowButton()をオーバーライドして別途三角形アイコンを使う方がよさそう
#code{{
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
public class ComboBoxInsetsTest {
  public JComponent makeUI() {
    UIManager.put("ComboBox.foreground", Color.WHITE);
    UIManager.put("ComboBox.background", Color.BLACK);
    UIManager.put("ComboBox.selectionForeground", Color.CYAN);
    UIManager.put("ComboBox.selectionBackground", Color.BLACK);

    UIManager.put("ComboBox.buttonDarkShadow", Color.BLACK);
    UIManager.put("ComboBox.buttonBackground", Color.WHITE);
    UIManager.put("ComboBox.buttonHighlight", Color.WHITE);
    UIManager.put("ComboBox.buttonShadow", Color.WHITE);

    UIManager.put("ComboBox.border", BorderFactory.createLineBorder(Color.WHITE));
    UIManager.put("ComboBox.editorBorder", BorderFactory.createLineBorder(Color.GREEN));

    DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
    model.addElement("aaaa");
    model.addElement("aaaabbb");
    model.addElement("aaaabbbcc");
    model.addElement("1234123512351234");
    model.addElement("bbb1");
    model.addElement("bbb12");
    JComboBox<String> combo = new JComboBox<>(model);
    combo.setUI(new BasicComboBoxUI());

    Object o = combo.getAccessibleContext().getAccessibleChild(0);
    ((JComponent)o).setBorder(BorderFactory.createMatteBorder(0,1,1,1,Color.WHITE));

    JPanel p = new JPanel();
    p.setOpaque(true);
    p.setBackground(Color.BLACK);
    p.add(combo);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new ComboBoxInsetsTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
}}

**参考リンク [#w8434b1f]
-[[JComboBoxにアイコンを表示>Swing/IconComboBox]]
-[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4515838 Bug ID: 4515838 Can't change the border of a JComboBox]

**コメント [#df84d3cd]
- %%なんだか、よく分からなくなってきましたorz。%% -- [[aterai]] &new{2008-03-11 (火) 21:38:58};
-- JDK 1.6.0_10-beta-b22 で、BasicComboBoxUIのpaddingにすこし修正が入っている?ようです。
- L&F の切り替えなどを追加しました。 -- [[aterai]] &new{2008-04-02 (水) 20:08:01};

#comment