Swing/CornerRibbonLabel のバックアップ(No.4)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/CornerRibbonLabel へ行く。
- 1 (2020-08-03 (月) 14:34:12)
- 2 (2020-08-03 (月) 16:25:01)
- 3 (2020-08-30 (日) 23:58:12)
- 4 (2022-03-06 (日) 07:24:12)
- category: swing
folder: CornerRibbonLabel
title: JLabelの隅に斜めに回転した文字列とリボンと重ねて表示する
tags: [JLabel, AffineTransform]
author: aterai
pubdate: 2020-08-03T14:31:02+09:00
description: JLabelの右上隅に斜め45度に回転した文字列とリボンと重ねて表示します。
image: https://drive.google.com/uc?id=1AbO4jLsaajRhg6M5GuBlsdZg6BIg3Abn
hreflang:
href: https://java-swing-tips.blogspot.com/2020/08/overlap-jlabel-with-ribbon-and-slanted.html lang: en
概要
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
に変換- 参考: Fontを回転する
- 文字列の
Shape
をその左下を原点にMath.toRadians(45d)
回転