TITLE:JComboBoxの内余白

JComboBoxの内余白

編集者:Terai Atsuhiro~

作成日:2007-05-28
更新日:2022-01-27 (木) 14:24:55
  • category: swing folder: PaddingComboBox title: JComboBoxの内余白 tags: [JComboBox, Border, LookAndFeel, JTextField] author: aterai pubdate: 2007-05-28T05:42:18+09:00 description: JComboBoxのエディタなどに内余白を設定します。 image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTQv1E_b9I/AAAAAAAAAgE/nxvnwwFoDyU/s800/PaddingComboBox.png

概要

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

概要

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

サンプルコード

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

#spandel
#screenshot
#spanend
#spanadd
JComboBox<String> combo = new JComboBox<String>(model) {
#spanend
  @Override public void updateUI() {
    setRenderer(null);
    super.updateUI();
    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);
  }
#spanadd
};
#spanend
#spanadd
View in GitHub: Java, Kotlin

サンプルコード

#spanend
#spandel
//Border padding = BorderFactory.createEmptyBorder(0,5,0,0);
#spanend
#spandel
Border padding = BorderFactory.createMatteBorder(0,5,0,0,new Color(1f,.9f,.9f));
#spanend
#spanadd
* 解説 [#explanation]
#spanend
#spanadd
上記のサンプルでは、`JComboBox`に`Border`(`EmptyBorder`と`MatteBorder`を切り替え可能)を設定した`ListCellRenderer`を設定して、ドロップダウンリストの左余白をすこし広げています。`JComboBox`が編集不可の場合、エディタ部分もこの余白が自動的に適用されます。
#spanend

#spandel
final ListCellRenderer lcr = combo00.getRenderer();
#spanend
#spandel
((JLabel)lcr).setBorder(padding);
#spanend
- `0`:編集不可
-- `ListCellRenderer`で余白を指定

#spandel
combo00.setRenderer(lcr);
#spanend
#spandel
combo01.setRenderer(lcr);
#spanend
#spandel
combo02.setRenderer(lcr);
#spanend
----

#spandel
combo00.setEditable(false);
#spanend
#spandel
combo01.setEditable(true);
#spanend
#spandel
combo02.setEditable(true);
#spanend
- `1`: `JComboBox`が編集可 + テキストフィールドの元`Border` + 任意の`Border`で余白を設定
-- `editor.setBorder(BorderFactory.createCompoundBorder(editor.getBorder(), padding));`
-- `JComboBox#getEditor()#getEditorComponent()`で取得した`JTextField`に余白を指定
-- `JDK 1.5`では余白を指定しても反映されない
-- `JDK 1.6`では取得した`JTextFieldをsetOpaque(true)`としないと背景色は反映されない

#spandel
JTextField editor = (JTextField) combo01.getEditor().getEditorComponent();
#spanend
#spandel
editor.setBorder(padding);
#spanend
#spandel
editor.setOpaque(true);
#spanend
#spandel
editor.setBackground(new Color(.9f,1f,.9f));
#spanend
- `2`: `JComboBox`が編集可 + テキストフィールドの元`Border`は無視して任意の`Border`のみで余白を設定
-- `editor.setBorder(padding);`
-- `JComboBox#getEditor()#getEditorComponent()`で取得した`JTextField`に余白を指定
-- `MetalLookAndFeel`でテキストフィールドの枠が描画できない

#spandel
combo02.setBorder(BorderFactory.createCompoundBorder(combo02.getBorder(), padding));
#spanend
#spandel
//combo02.setOpaque(true);
#spanend
#spandel
//combo02.setBackground(new Color(.9f,1f,.9f));
#spanend
#spandel
  • &jnlp;
  • &jar;
  • &zip;
    • -

解説

JComboBoxが編集不可の場合、ListCellRendererで余白を指定することが出来ます。上記のサンプルでは、EmptyBorderの代わりにMatteBorderを使って余白を着色してテストしています。
  • 3: JComboBoxが編集可 + テキストフィールドのInsets + 5ピクセル余白を設定
    • editor.setMargin(new Insets(i.top,i.left+5,i.bottom,i.right));
    • MetalLookAndFeelMotifLookAndFeelWindowsLookAndFeelなどでは無効
    • NimbusLookAndFeelでは有効だがJComboBoxの高さなども変化してしまう
  • 上:編集不可
    • ListCellRendererで余白を指定
  • 4: JComboBoxが編集可 + テキストフィールドのMargin + 5ピクセル余白を設定
    • editor.setMargin(new Insets(m.top,m.left+5,m.bottom,m.right));
    • MetalLookAndFeelMotifLookAndFeelWindowsLookAndFeelなどでは無効
    • NimbusLookAndFeelでは有効
  • 中:編集可
    • ListCellRendererで余白を指定
    • JComboBox#getEditor()#getEditorComponent()で取得したJTextFieldに余白を指定
    • JDK 1.5 では余白を指定しても反映されない
    • JDK 1.6 では取得したJTextFieldをsetOpaque(true)としないと背景色は反映されない
      • -
  • 下:編集可
    • ListCellRendererで余白を指定
    • JComboBox#setBorder()で、元のBorderの内側に余白を指定
    • JDK 1.6 では余計な?余白が発生する
  • 5: JComboBoxが編集可 + JComboBoxBorder + 任意のBorderで余白をJComboBox自身に設定
    • JComboBox#setBorder()で元のBorderの内側に余白を指定
    • WindowsLookAndFeelMotifLookAndFeelで有効?
    • MetalLookAndFeelNimbusLookAndFeelではJComboBoxの外側に余白が付く
  • 6: JComboBoxが編集可 + JComboBoxBorder + 任意のBorderで余白をJComboBox自身に設定
    • JComboBox#setBorder()で元のBorderの外側に余白を指定
    • WindowsLookAndFeelで余計な枠が表示される?

以下のようにエディタにMarginを指定しても無視されるようです。
  • その他にも、以下のようにUIManagerで余白を設定する方法もあるがLookAndFeelによって対応が異なる? ComboBox.paddingは無くなっている?
    • JComboBoxが編集可能の場合はComboBox.editorBorderが有効かもしれない
      #spandel
      editor = (JTextField) combo.getEditor().getEditorComponent();
      #spanend
      #spandel
      Insets m = editor.getMargin();
      #spanend
      #spandel
      Insets margin = new Insets(m.top,m.left+10,m.bottom,m.right);
      #spanend
      #spandel
      //System.out.println(margin.toString());
      #spanend
      #spandel
      editor.setMargin(margin);
      #spanend
      #spanadd
      // UIManager.put("ComboBox.padding", new InsetsUIResource(insets));
      #spanend
      #spanadd
      UIManager.put("ComboBox.editorBorder", BorderFactory.createEmptyBorder(0, 5, 0, 0));
      #spanend
      
  • 追記
    • 無視されるのは、BasicLaF系(WindowsLaFなど)で、SynthLaF系(Nimbus, GTKなど)では上記の設定は有効になる?
    • 1.6.0_10-beta-b13 では、BasicLaF系はUIManager.put("ComboBox.padding", insets) が使用できる?
  • 上記のサンプルを余白に色無しにしてUbuntu 7.04(GNOME 2.18.1)、JDK 1.6.0で実行すると、以下のように表示される
    PaddingComboBox1.png

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

#screenshot(,screenshot1.png)

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

参考リンク

参考リンク

コメント

  • なんだか、よく分からなくなってきましたorz。 -- terai

コメント