TITLE:JComboBoxの内余白

Posted by aterai at 2007-05-28

JComboBoxの内余白

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

  • &jnlp;
  • &jar;
  • &zip;
PaddingComboBox.png

サンプルコード

Border padding = BorderFactory.createEmptyBorder(0,5,0,0);
ListCellRenderer lcr = combo.getRenderer();
((JLabel)lcr).setBorder(padding);
combo.setRenderer(lcr);

解説

上記のサンプルでは、JComboBox に、Border*1を設定した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 で余計な枠が表示される?

その他にも、以下のように余白を設定する方法もありますが、L&F によって対応が異なるようです。

UIManager.put("ComboBox.padding", new InsetsUIResource(insets));

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

PaddingComboBox1.png

  • Look&Feel毎にJComboBoxの余白の描画は異なるみたいなので、全部まとめて消すのは難しい?
  • BasicComboBoxUI も、ComboBox.buttonDarkShadow がArrowButtonの三角とボタンの影に使われていて微妙
    • BasicComboBoxUI#createArrowButton()をオーバーライドして別途三角形アイコンを使う方がよさそう
      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);
        }
      }
      

参考リンク

コメント

  • なんだか、よく分からなくなってきましたorz。 -- aterai
    • JDK 1.6.0_10-beta-b22 で、BasicComboBoxUIのpaddingにすこし修正が入っている?ようです。
  • L&F の切り替えなどを追加しました。 -- aterai