---
category: swing
folder: FiveStarRatingLabel
title: GlyphVectorで作成した5段階評価の結果をラベルに描画する
tags: [GlyphVector, Font, JLabel]
author: aterai
pubdate: 2022-05-16T02:25:26+09:00
description: GlyphVectorを使用して5段階評価の★のアウトラインを作成し、その内部を評価値の小数点一位まで塗りつぶします。
image: https://drive.google.com/uc?id=1qWNar6LNSc0eR0JQQL9exGtmmmNfL-ki
---
* 概要 [#summary]
GlyphVectorを使用して5段階評価の★のアウトラインを作成し、その内部を評価値の小数点一位まで塗りつぶします。
`GlyphVector`を使用して`5`段階評価の★のアウトラインを作成し、その内部を評価値の小数点一位まで塗りつぶします。

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

* サンプルコード [#sourcecode]
#code(link){{
// JComponent label1 = new FiveStarRatingLabel("3.5");
class FiveStarRatingLabel extends JComponent {
  private static final String STAR = "★★★★★";
  private final int ip;
  private final int fp;

  protected FiveStarRatingLabel(String rating) {
    super();
    BigDecimal bd = new BigDecimal(rating);
    ip = bd.intValue();
    fp = bd.subtract(new BigDecimal(ip)).multiply(BigDecimal.TEN).intValue();
  }

  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int w = getWidth();
    int h = getHeight();
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, w, h);

    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    FontRenderContext frc = g2.getFontRenderContext();
    GlyphVector gv = getFont().createGlyphVector(frc, STAR);
    Rectangle2D r = gv.getVisualBounds();

    double cx = w / 2d - r.getCenterX();
    double cy = h / 2d - r.getCenterY();
    AffineTransform toCenterAtf = AffineTransform.getTranslateInstance(cx, cy);

    double point = 0d;
    for (int i = 0; i < gv.getNumGlyphs(); i++) {
      GlyphMetrics gm = gv.getGlyphMetrics(i);
      if (i <= ip - 1) {
        point += gm.getAdvance();
      } else if (i <= ip) {
        point += gm.getBounds2D().getWidth() * fp / 10d;
      }
    }
    g2.setPaint(Color.GREEN);
    Shape s = toCenterAtf.createTransformedShape(gv.getOutline());
    g2.draw(s);
    Rectangle2D clip = new Rectangle2D.Double(r.getX(), r.getY(), point, r.getHeight());
    g2.setClip(toCenterAtf.createTransformedShape(clip));
    g2.fill(s);
    g2.dispose();
  }
}
}}

* 解説 [#explanation]
- `5`段階評価用に★を`5`文字分用意
- `Font#createGlyphVector(...)`でその文字列★★★★★から`GlyphVector`を作成
- `GlyphVector#getGlyphMetrics(index)`で一文字ごとに`GlyphMetrics`を取得
-- 評価値の整数部(★一つ個分)は`GlyphMetrics#getAdvance()`で幅を取得
-- 評価値の小数部は小数点一位を`10`倍して`BigDecimal`で整数として取得し、`GlyphMetrics#getBounds2D()#getWidth() * fractionalPart / 10d`で幅に変換
- この合計幅の矩形で`Clip`した領域のみ文字列★のアウトラインを塗りつぶして評価値を描画

* 参考リンク [#reference]
- [[RGBImageFilterでアイコンの色調を変更>Swing/RatingLabel]]
- [[Fontのアウトラインを取得して文字列の内部を修飾する>Swing/LineSplittingLabel]]
- [[Fontに長体をかけてJTextAreaで使用する>Swing/CondensedFontLabel]]

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