Swing/ClockWithArabicOrRomanNumerals のバックアップ(No.10)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ClockWithArabicOrRomanNumerals へ行く。
- 1 (2022-08-22 (月) 00:19:27)
- 2 (2022-08-22 (月) 03:49:38)
- 3 (2022-08-22 (月) 12:25:24)
- 4 (2022-08-22 (月) 14:11:11)
- 5 (2022-08-23 (火) 02:54:28)
- 6 (2022-08-31 (水) 05:29:35)
- 7 (2022-09-08 (木) 03:36:12)
- 8 (2022-09-12 (月) 08:32:03)
- 9 (2022-09-14 (水) 05:27:25)
- 10 (2022-10-03 (月) 00:46:34)
- 11 (2022-11-12 (土) 09:07:27)
- 12 (2023-03-18 (土) 16:06:27)
- 13 (2024-06-06 (木) 14:57:57)
- category: swing
folder: ClockWithArabicOrRomanNumerals
title: AffineTransformを使用してアナログ時計の文字盤に数字を配置する
tags: [AffineTransform, Font, TextLayout, TextAttribute, JPanel]
author: aterai
pubdate: 2022-08-22T00:18:25+09:00
description: AffineTransformを使用してアナログ時計の文字盤にアラビア数字やローマ数字を配置します。
image: https://drive.google.com/uc?id=1lJ0MWGTsDflFSRzI8m5spBQZ6Ls_RT1m
hreflang:
href: https://java-swing-tips.blogspot.com/2022/08/use-affinetransform-to-place-roman.html lang: en
概要
AffineTransform
を使用してアナログ時計の文字盤にアラビア数字やローマ数字を配置します。
Screenshot
Advertisement
サンプルコード
private void paintClockNumbers(Graphics2D g2, double radius, double hourMarkerLen) {
AffineTransform at = AffineTransform.getRotateInstance(0d);
g2.setColor(Color.WHITE);
Font font = g2.getFont();
FontRenderContext frc = g2.getFontRenderContext();
if (isRomanNumerals) {
AffineTransform si = AffineTransform.getScaleInstance(1d, 2d);
for (String txt : romanNumerals) {
Shape s = getTextLayout(txt, font, frc).getOutline(si);
Rectangle2D r = s.getBounds2D();
double tx = r.getCenterX();
double ty = radius - hourMarkerLen - r.getHeight() + r.getCenterY() * .5;
Shape t = AffineTransform.getTranslateInstance(-tx, -ty).createTransformedShape(s);
g2.fill(at.createTransformedShape(t));
at.rotate(Math.PI / 6d);
}
} else {
Point2D ptSrc = new Point2D.Double();
for (String txt : arabicNumerals) {
Shape s = getTextLayout(txt, font, frc).getOutline(null);
Rectangle2D r = s.getBounds2D();
double ty = radius - hourMarkerLen - r.getHeight() - r.getCenterY() * .5;
ptSrc.setLocation(0d, -ty);
Point2D pt = at.transform(ptSrc, null);
double dx = pt.getX() - r.getCenterX();
double dy = pt.getY() - r.getCenterY();
// g2.drawString(txt, (float) dx, (float) dy);
g2.fill(AffineTransform.getTranslateInstance(dx, dy).createTransformedShape(s));
at.rotate(Math.PI / 6d);
}
}
}
private static TextLayout getTextLayout(String txt, Font font, FontRenderContext frc) {
return new TextLayout(txt, font, frc);
}
View in GitHub: Java, Kotlin解説
- アラビア数字
Font
に負のトラッキング値(字送り、文字間)を設定して文字列幅を縮小- アラビア数字文字列から
Font
やTextLayout
を使用して文字図形を取得 - 時計の中心から
12
時の位置までPoint
を移動 - 時計の中心を原点にプラス
30°
回転をAffineTransform
に追加してPoint
を回転 Point
が文字図形の中心になるよう座標を調整して文字図形を描画Graphics#drawString(...)
メソッドで数字文字列
- ローマ数字
Font
に負のトラッキング値(字送り、文字間)を設定して文字列幅を縮小- ローマ数字文字列から
Font
やTextLayout
を使用して高さのみ200%
拡大した文字図形を取得 - 時計の中心から
12
時の位置まで文字図形を移動 - 時計の中心を原点にプラス
30°
回転をAffineTransform
に追加して文字図形を回転