TITLE:JComboBoxのBorderを変更する
Posted by at 2012-02-20

JComboBoxのBorderを変更する

JComboBoxの表示部分、矢印ボタン、ドロップダウンリストのBorderや色を変更します。
  • category: swing folder: ComboBoxBorder title: JComboBoxのBorderを変更する tags: [JComboBox, UIManager, Border, ArrowButton, MouseListener, BasicComboPopup] author: aterai pubdate: 2012-02-20T16:53:02+09:00 description: JComboBoxの表示部分、矢印ボタン、ドロップダウンリストのBorderや色を変更します。 image: https://lh3.googleusercontent.com/-jHpgdiBwt6s/T0H3deyce_I/AAAAAAAABJY/_3k6-paq4lM/s800/ComboBoxBorder.png

概要

JComboBoxの表示部分、矢印ボタン、ドロップダウンリストのBorderや色を変更します。
ComboBoxBorder.png

サンプルコード

サンプルコード

#spandel
//ComboBox.border
#spanend
#spanadd
// ComboBox.border
#spanend
UIManager.put("ComboBox.border", BorderFactory.createLineBorder(Color.WHITE));

#spandel
//ArrowButton
#spanend
#spanadd
// ArrowButton
#spanend
combo.setUI(new BasicComboBoxUI() {
  @Override protected JButton createArrowButton() {
    JButton b = new JButton(new ArrowIcon()); //.createArrowButton();
    JButton b = new JButton(new ArrowIcon()); // .createArrowButton();
    b.setBackground(Color.BLACK);
    b.setContentAreaFilled(false);
    b.setFocusPainted(false);
    b.setBorder(BorderFactory.createEmptyBorder());
    return b;
  }
});

#spandel
//DropDownList
#spanend
#spanadd
// DropDownList
#spanend
Object o = combo.getAccessibleContext().getAccessibleChild(0);
#spandel
((JComponent)o).setBorder(BorderFactory.createMatteBorder(0,1,1,1,Color.WHITE));
#spanend
#spanadd
((JComponent) o).setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.WHITE));
#spanend
View in GitHub: Java, Kotlin

解説

  • 上: MetalComboBoxUI
    • UIManager.put("ComboBox.border", border)などで、Borderを変更しているが、UI独自の余白?を消すことができない

解説

  • 上: MetalComboBoxUI
    • UIManager.put("ComboBox.border", border)などでBorderを変更しているが、これとは別にUIで独自に余白が描画される
    • MetalComboBoxUI独自の余白を消す場合はMetalThemeを変更してMetalLookAndFeel.getControlShadow()を同色にするか、MetalComboBoxUI#paintCurrentValueBackground(...)をオーバーライドする必要がある
  • 中: BasicComboBoxUI
    • MetalComboBoxUIなどに存在する余白は消すことができるがComboBox.buttonDarkShadowArrowButtonの三角とボタンの影に使用されているため両方を一度に非表示にできない
  • 下: BasicComboBoxUI#createArrowButton()
    • BasicComboBoxUI#createArrowButton()をオーバーライドして独自のアイコンをもつJButtonを使用するように変更
    • JComboBoxMouseListenerを追加してマウスカーソルがJComboBox内にある場合、ArrowButtonHover表示されるように設定
  • 中: BasicComboBoxUI
    • MetalComboBoxUIなどにあった余白は消すことができるが、ComboBox.buttonDarkShadow がArrowButtonの三角とボタンの影に使用されているため、両方を一度に非表示にすることができない
  • 下: BasicComboBoxUI#createArrowButton()
    • BasicComboBoxUI#createArrowButton()をオーバーライドして、独自のアイコンをもつJButtonを使用するように変更
    • JComboBoxにMouseListenerを追加して、マウスカーソルがJComboBox内にある場合、ArrowButtonがHover表示されるように設定
      combo.addMouseListener(new MouseAdapter() {
        private ButtonModel getButtonModel(MouseEvent e) {
          JComboBox cb = (JComboBox)e.getSource();
          JButton b = (JButton)cb.getComponent(0);
          JComboBox<?> cb = (JComboBox<?>) e.getComponent();
          JButton b = (JButton) cb.getComponent(0);
          return b.getModel();
        }
      #spanadd
      
      #spanend
        @Override public void mouseEntered(MouseEvent e) {
          getButtonModel(e).setRollover(true);
        }
      #spanadd
      
      #spanend
        @Override public void mouseExited(MouseEvent e) {
          getButtonModel(e).setRollover(false);
        }
      #spanadd
      
      #spanend
        @Override public void mousePressed(MouseEvent e) {
          getButtonModel(e).setPressed(true);
        }
      #spanadd
      
      #spanend
        @Override public void mouseReleased(MouseEvent e) {
          getButtonModel(e).setPressed(false);
        }
      });
      

java - How do you change border of the pop up section of a JComboBox? - Stack Overflow を参考にして、JComboBoxから以下のように、BasicComboPopupを取得し、MatteBorderを設定 java - How do you change border of the pop up section of a JComboBox? - Stack Overflow を参考に、JComboBoxから以下のようにBasicComboPopupを取得してMatteBorderを設定
Object o = combo.getAccessibleContext().getAccessibleChild(0);
#spandel
((JComponent)o).setBorder(BorderFactory.createMatteBorder(0,1,1,1,Color.WHITE));
#spanend
#spanadd
((JComponent) o).setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.WHITE));
#spanend

参考リンク

#spanend
#spanadd
import java.awt.*;
#spanend
#spanadd
import java.awt.event.*;
#spanend
#spanadd
import javax.swing.*;
#spanend
#spanadd
import javax.swing.text.*;
#spanend
#spanadd
import javax.swing.plaf.*;
#spanend
#spanadd
import javax.swing.plaf.basic.*;
#spanend
#spanadd
import javax.swing.plaf.metal.*;
#spanend
#spanadd

#spanend
#spanadd
public class ComboBoxUIDemo {
#spanend
  private static Color BORDER = Color.GRAY;
  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);
#spanadd

#spanend
    // UIManager.put("ComboBox.buttonDarkShadow", Color.WHITE);
    // UIManager.put("ComboBox.buttonBackground", Color.GRAY);
    // UIManager.put("ComboBox.buttonHighlight", Color.WHITE);
    // UIManager.put("ComboBox.buttonShadow", Color.WHITE);
    // UIManager.put("ComboBox.editorBorder", BorderFactory.createLineBorder(Color.RED));
#spanadd

#spanend
    Box box = Box.createVerticalBox();
#spanadd

#spanend
    UIManager.put("ComboBox.border", BorderFactory.createEmptyBorder());
    for (int i = 0; i < 2; i++) { // Default
      JComboBox<String> cb = new JComboBox<>(makeModel());
      if (i % 2 == 0) setEditable(cb);
      setPopupBorder(cb);
      box.add(cb);
      box.add(Box.createVerticalStrut(10));
    }
#spanadd

#spanend
    {
      // Override MetalComboBoxUI#paintCurrentValueBackground(...)
      JComboBox<String> cb = new JComboBox<>(makeModel());
      cb.setUI(new MetalComboBoxUI() {
        @Override public void paintCurrentValueBackground(
          Graphics g, Rectangle bounds, boolean hasFocus) {
          // if (MetalLookAndFeel.usingOcean()) {
          if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme) {
            g.setColor(MetalLookAndFeel.getControlDarkShadow());
            g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height - 1);
            // COMMENTOUT>>>
            // g.setColor(MetalLookAndFeel.getControlShadow());
            // g.drawRect(bounds.x + 1, bounds.y + 1, bounds.width - 2,
            //            bounds.height - 3);
            // <<<COMMENTOUT
            if (hasFocus && !isPopupVisible(comboBox) && arrowButton != null) {
              g.setColor(listBox.getSelectionBackground());
              Insets buttonInsets = arrowButton.getInsets();
              if (buttonInsets.top > 2) {
                g.fillRect(bounds.x + 2, bounds.y + 2, bounds.width - 3,
                           buttonInsets.top - 2);
              }
              if (buttonInsets.bottom > 2) {
                g.fillRect(bounds.x + 2, bounds.y + bounds.height -
                           buttonInsets.bottom, bounds.width - 3,
                           buttonInsets.bottom - 2);
              }
            }
          } else if (g == null || bounds == null) {
            throw new NullPointerException(
              "Must supply a non-null Graphics and Rectangle");
          }
        }
      });
      setPopupBorder(cb);
#spanadd

#spanend
      box.add(cb);
      box.add(Box.createVerticalStrut(10));
    }
#spanadd

#spanend
    UIManager.put("ComboBox.border", BorderFactory.createLineBorder(BORDER));
    for (int i = 0; i < 2; i++) { // BasicComboBoxUI
      JComboBox<String> cb = new JComboBox<>(makeModel());
      if (i % 2 == 0) setEditable(cb);
      cb.setUI(new BasicComboBoxUI());
      setPopupBorder(cb);
      box.add(cb);
      box.add(Box.createVerticalStrut(10));
    }
#spanadd

#spanend
    JPanel p = new JPanel(new BorderLayout());
    p.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
    p.add(box, BorderLayout.NORTH);
    return p;
  }
#spanadd

#spanend
  private static void setEditable(JComboBox cb) {
    cb.setEditable(true);
    ComboBoxEditor editor = cb.getEditor();
    Component c = editor.getEditorComponent();
    if (c instanceof JTextField) {
      JTextField tf = (JTextField) c;
      tf.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, BORDER));
    }
  }
#spanadd

#spanend
  private static void setPopupBorder(JComboBox cb) {
    Object o = cb.getAccessibleContext().getAccessibleChild(0);
    JComponent c = (JComponent) o;
    c.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, BORDER));
  }
#spanadd

#spanend
  private static DefaultComboBoxModel<String> makeModel() {
    DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
    m.addElement("1234");
    m.addElement("5555555555555555555555");
    m.addElement("6789000000000");
    return m;
  }
#spanadd

#spanend
  public static void main(String[] args) {
#spanadd
//     OceanTheme theme = new OceanTheme() {
#spanend
#spanadd
//       @Override protected ColorUIResource getSecondary2() {
#spanend
#spanadd
//         return new ColorUIResource(Color.RED);
#spanend
#spanadd
//       }
#spanend
#spanadd
//     };
#spanend
#spanadd
//     MetalLookAndFeel.setCurrentTheme(theme);
#spanend
#spanadd

#spanend
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
#spanadd

#spanend
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new ComboBoxUIDemo().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
#spanadd
}
#spanend
#spanadd

参考リンク

コメント

コメント