JLabelの隅に斜めに回転した文字列とリボンと重ねて表示する
Total: 2396
, Today: 3
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JLabel
の右上隅に斜め45
度に回転した文字列とリボンと重ねて表示します。
Screenshot
Advertisement
サンプルコード
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);
}
}
View in GitHub: Java, Kotlin解説
JLabel
JLabel#isOpaque()
をオーバーライドして透明化JLabel#paintComponent(...)
をオーバーライドして背景用のラウンド矩形、JLabel
の元アイコン、右上隅のリボン、リボン文字列の順に描画
- リボン
- 親
JLabel
の上辺x
軸中央付近にリボンの左下が配置されるように矩形を作成 - リボン矩形の左下を原点に
Math.toRadians(45d)
回転
- 親
- リボン文字列
TextLayout.getOutline()
メソッドで文字列をShape
に変換- 文字列の
Shape
をその左下を原点にMath.toRadians(45d)
回転