Reputation: 113
I want make JComboBox has rounded corners. And i came with this code :
public class BPosCmbBox extends JCboEdc {
public BPosCmbBox() {
super();
setBorder(new RoundBorder());
}
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
super.paint(g); //To change body of generated methods, choose Tools | Templates.
}
}
public class RoundBorder extends AbstractBorder {
Color bgColor = new Color(0, 0, 0, 220);
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
((Graphics2D) g).setColor(bgColor);
((Graphics2D) g).drawRoundRect(x, y, width - 1, height - 1, 12, 12);
}
public Insets getBorderInsets(Component c) {
return new Insets(3, 6, 3, 3);
}
public Insets getBorderInsets(Component c, Insets insets) {
insets.top = insets.left = insets.bottom = insets.right = 3;
return insets;
}
}
But it still has square box inside like this
Is there any way to remove square box inside? And is this possible to has drop down list with rounded corners too?
Upvotes: 1
Views: 2804
Reputation: 9833
Here's my version, using BasicComboBoxUI
instead of MetalComboBoxUI
:
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import javax.accessibility.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
public class RoundedCornerComboBoxTest {
private static final Color BACKGROUND = Color.BLACK;
private static final Color FOREGROUND = Color.WHITE;
private static final Color SELECTIONFOREGROUND = Color.ORANGE;
private JComponent makeUI() {
UIManager.put("ComboBox.foreground", FOREGROUND);
UIManager.put("ComboBox.background", BACKGROUND);
UIManager.put("ComboBox.selectionForeground", SELECTIONFOREGROUND);
UIManager.put("ComboBox.selectionBackground", BACKGROUND);
UIManager.put("ComboBox.buttonDarkShadow", BACKGROUND);
UIManager.put("ComboBox.buttonBackground", FOREGROUND);
UIManager.put("ComboBox.buttonHighlight", FOREGROUND);
UIManager.put("ComboBox.buttonShadow", FOREGROUND);
UIManager.put("ComboBox.border", new RoundedCornerBorder());
JComboBox<String> combo1 = new JComboBox<>(makeModel());
combo1.setUI(new BasicComboBoxUI());
Object o = combo1.getAccessibleContext().getAccessibleChild(0);
if (o instanceof JComponent) {
JComponent c = (JComponent) o;
c.setBorder(new RoundedCornerBorder());
c.setForeground(FOREGROUND);
c.setBackground(BACKGROUND);
}
combo1.addPopupMenuListener(new HeavyWeightContainerListener());
UIManager.put("ComboBox.border", new RoundedCornerBorder1());
JComboBox<String> combo2 = new JComboBox<>(makeModel());
combo2.setUI(new BasicComboBoxUI());
o = combo2.getAccessibleContext().getAccessibleChild(0);
if (o instanceof JComponent) {
JComponent c = (JComponent) o;
c.setBorder(new RoundedCornerBorder2());
c.setForeground(FOREGROUND);
c.setBackground(BACKGROUND);
}
combo2.addPopupMenuListener(new HeavyWeightContainerListener());
JPanel p = new JPanel();
p.add(combo1);
p.add(combo2);
p.setOpaque(true);
p.setBackground(Color.GRAY);
return p;
}
private static DefaultComboBoxModel<String> makeModel() {
DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
m.addElement("1234");
m.addElement("5555555555555555555555");
m.addElement("6789000000000");
return m;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new RoundedCornerComboBoxTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class HeavyWeightContainerListener implements PopupMenuListener {
@Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
JComboBox combo = (JComboBox) e.getSource();
Accessible a = combo.getUI().getAccessibleChild(combo, 0);
if (a instanceof BasicComboPopup) {
BasicComboPopup pop = (BasicComboPopup) a;
Container top = pop.getTopLevelAncestor();
if (top instanceof JWindow) {
//http://ateraimemo.com/Swing/DropShadowPopup.html
System.out.println("HeavyWeightContainer");
((JWindow) top).setBackground(new Color(0x0, true));
}
}
}
});
}
@Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
@Override public void popupMenuCanceled(PopupMenuEvent e) {}
}
class RoundedCornerBorder extends AbstractBorder {
protected static final int ARC = 12;
@Override public void paintBorder(
Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int r = ARC;
int w = width - 1;
int h = height - 1;
Area round = new Area(new RoundRectangle2D.Float(x, y, w, h, r, r));
if (c instanceof JPopupMenu) {
g2.setPaint(c.getBackground());
g2.fill(round);
} else {
Container parent = c.getParent();
if (Objects.nonNull(parent)) {
g2.setPaint(parent.getBackground());
Area corner = new Area(new Rectangle2D.Float(x, y, width, height));
corner.subtract(round);
g2.fill(corner);
}
}
g2.setPaint(c.getForeground());
g2.draw(round);
g2.dispose();
}
@Override public Insets getBorderInsets(Component c) {
return new Insets(4, 8, 4, 8);
}
@Override public Insets getBorderInsets(Component c, Insets insets) {
insets.set(4, 8, 4, 8);
return insets;
}
}
class RoundedCornerBorder1 extends RoundedCornerBorder {
//http://ateraimemo.com/Swing/RoundedComboBox.html
@Override public void paintBorder(
Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int r = ARC;
int w = width - 1;
int h = height - 1;
Area round = new Area(new RoundRectangle2D.Float(x, y, w, h, r, r));
Rectangle b = round.getBounds();
b.setBounds(b.x, b.y + r, b.width, b.height - r);
round.add(new Area(b));
Container parent = c.getParent();
if (Objects.nonNull(parent)) {
g2.setPaint(parent.getBackground());
Area corner = new Area(new Rectangle2D.Float(x, y, width, height));
corner.subtract(round);
g2.fill(corner);
}
g2.setPaint(c.getForeground());
g2.draw(round);
g2.dispose();
}
}
class RoundedCornerBorder2 extends RoundedCornerBorder {
@Override public void paintBorder(
Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int r = ARC;
int w = width - 1;
int h = height - 1;
Path2D.Float p = new Path2D.Float();
p.moveTo(x, y);
p.lineTo(x, y + h - r);
p.quadTo(x, y + h, x + r, y + h);
p.lineTo(x + w - r, y + h);
p.quadTo(x + w, y + h, x + w, y + h - r);
p.lineTo(x + w, y);
p.closePath();
Area round = new Area(p);
g2.setPaint(c.getBackground());
g2.fill(round);
g2.setPaint(c.getForeground());
g2.draw(round);
g2.setPaint(c.getBackground());
g2.drawLine(x + 1, y, x + width - 2, y);
g2.dispose();
}
}
Upvotes: 5