<
Code
class BadgeLabel extends JLabel {
private final Color ribbonColor = new Color(0xAA_FF_64_00, true);
private final String ribbonText;
protected BadgeLabel(Icon image) {
super(image);
this.ribbonText = null;
}
protected BadgeLabel(Icon image, String ribbonText) {
super(image);
this.ribbonText = ribbonText;
}
@Override public void updateUI() {
super.updateUI();
setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
setVerticalAlignment(SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.BOTTOM);
setHorizontalAlignment(SwingConstants.CENTER);
setHorizontalTextPosition(SwingConstants.CENTER);
}
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.WHITE);
g2.fill(getShape());
super.paintComponent(g);
if (ribbonText != null) {
Dimension d = getSize();
float fontSize = 10f;
int cx = (d.width - (int) fontSize) / 2;
double theta = Math.toRadians(45d);
Font font = g2.getFont().deriveFont(fontSize);
g2.setFont(font);
FontRenderContext frc = new FontRenderContext(null, true, true);
Shape ribbon = new Rectangle2D.Double(cx, -fontSize, d.width, fontSize);
AffineTransform at = AffineTransform.getRotateInstance(theta, cx, 0);
g2.setPaint(ribbonColor);
g2.fill(at.createTransformedShape(ribbon));
TextLayout tl = new TextLayout(ribbonText, font, frc);
g2.setPaint(Color.WHITE);
Rectangle2D r = tl.getOutline(null).getBounds2D();
double dx = cx + (d.width - cx) / Math.sqrt(2d) - r.getWidth() / 2d;
double dy = fontSize / 2d + r.getY();
AffineTransform tx = AffineTransform.getTranslateInstance(dx, dy);
Shape s = tl.getOutline(tx);
g2.fill(at.createTransformedShape(s));
}
g2.dispose();
}
@Override public boolean isOpaque() {
return false;
}
protected Shape getShape() {
Dimension d = getSize();
double r = d.width / 2d;
return new RoundRectangle2D.Double(
0d, 0d, d.width - 1d, d.height - 1d, r, r);
}
}
Explanation
JLabel
- Override
JLabel#isOpaque()
to make it transparent
- Overrides
JLabel#paintComponent(...)
to draw a round rectangle for the background, then the original icon for `JLabel`, then the ribbon in the upper right corner, then the ribbon string
Ribbon
- Create a
Rectangle
for the ribbon so that the lower left of the ribbon is positioned near the middle of the x axis of the parent JLabel
- Rotate the lower left corner of the ribbon rectangle 45 degrees(
Math.toRadians(45d)
) about the origin
Ribbon string
- Convert the Ribbon string to
Shape
using the TextLayout.getOutline(...)
method
- Rotate this
Shape
45 degrees from its bottom left
References
No comments:
Post a Comment