---
category: swing
folder: KnockoutTextLabel
title: JLabelのテキストで背景画像を切り抜いて表示する
tags: [JLabel, Font, GlyphVector, Graphics, Area]
author: aterai
pubdate: 2020-12-14T02:32:02+09:00
description: JLabelに描画した背景画像をテキストの図形で切り抜いたように表示します。
image: https://drive.google.com/uc?id=1KAsr3O8es4_eQzJc8N4DLBs9vIB-eJMx
---
* 概要 [#summary]
`JLabel`に描画した背景画像をテキストの図形で切り抜いたように表示します。

#download(https://drive.google.com/uc?id=1KAsr3O8es4_eQzJc8N4DLBs9vIB-eJMx)

* サンプルコード [#sourcecode]
#code(link){{
JLabel label = new JLabel("ABC") {
  @Override protected void paintComponent(Graphics g) {
    // super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    FontRenderContext frc = g2.getFontRenderContext();
    String text = getText();
    GlyphVector gv = getFont().createGlyphVector(frc, text);
    Rectangle2D b = gv.getVisualBounds();
    double w = getWidth();
    double h = getHeight();
    double cx = w / 2d - b.getCenterX();
    double cy = h / 2d - b.getCenterY();
    AffineTransform toCenterAtf = AffineTransform.getTranslateInstance(cx, cy);
    Shape s = toCenterAtf.createTransformedShape(gv.getOutline());
    AffineTransform toCenter = AffineTransform.getTranslateInstance(cx, cy);
    Shape s = toCenter.createTransformedShape(gv.getOutline());
    Area bg = new Area(new Rectangle2D.Double(0d, 0d, w, h));
    bg.subtract(new Area(s));
    g2.setColor(getBackground());
    g2.fill(bg);
    g2.dispose();
  }
};
label.setBackground(new Color(0xE6_00_00_32, true));
label.setFont(new Font(Font.SERIF, Font.BOLD, 140));
}}

* 解説 [#explanation]
- `JLabel#paintComponent(...)`をオーバーライドして背景画像を描画
- `Font#createGlyphVector(frc, "ABC")`で`GlyphVector`を生成
- `GlyphVector#getOutline()`でテキストの図形(`Shape`)を取得
-- [[Fontのアウトラインを取得して文字列の内部を修飾する>Swing/LineSplittingLabel]]
- `JLabel`の矩形からテキストの図形を切り抜いた図形を`Area#subtract(...)`で生成して背景色で塗り潰す
-- 背景色は`hasAlpha`にチェックがある場合は半透明に設定

* 参考リンク [#reference]
- [[Fontのアウトラインを取得して文字列の内部を修飾する>Swing/LineSplittingLabel]]

* コメント [#comment]
#comment
#comment