使用仿射变换将字体大小设置为与Swing中的容器成比例

时间:2013-11-14 22:22:44

标签: java swing fonts awt java-2d

那么,与SO上的类似问题略有不同,但我对如何使用转换转换缩小或增长文本字符串以使整体大小与要绘制的区域成比例有任何见解?

例如,我希望字体是该区域宽度的50%。

我继承了这样的代码,但我真的不明白它在做什么

Font font = new Font("Arial", Font.BOLD, 12);
FontRenderContext context = graphics.getFontRenderContext();
graphics.setFont(font);
Rectangle2D bounds = graphics.getFont().getStringBounds("Hello world", context);

LineMetrics line = font.getLineMetrics(text, context);
float xScale = (float) (region.width / bounds.getWidth());
float yScale = (region.height / (line.getAscent() + line.getDescent()));

double x = region.x;
double y = region.y + region.height - (yScale * line.getDescent());
AffineTransform transformation = AffineTransform.getTranslateInstance(x, y);

if (xScale > yScale)
    transformation.scale(yScale, yScale);
else
    transformation.scale(xScale, xScale);

graphics.setFont(font.deriveFont(transformation));
graphics.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);

int centerX = region.width / 2;
int centerY = region.height / 2;
graphics.drawString(text, centerX, centerY - (int) bounds.getHeight());

似乎将尺寸设定为合理的尺寸,但并未将其置于该区域的中心位置。如果你可以了解尝试做什么,那就太好了。

任何指针(只要它们不是字体指向java字体教程)都非常感激。

1 个答案:

答案 0 :(得分:3)

基本上,这似乎“试图”将文本置于“给定”区域中心......

// Set the base, start font
Font font = new Font("Arial", Font.BOLD, 12);
// Get rendering context
FontRenderContext context = graphics.getFontRenderContext();
// Set the font used by the graphics context...
graphics.setFont(font);
// Get the rectangle "bounds" of the text
Rectangle2D bounds = graphics.getFont().getStringBounds("Hello world", context);
// Get the line metrics, which describes things like the fonts decent and ascent
LineMetrics line = font.getLineMetrics(text, context);
// Calculate the scaling requirements
float xScale = (float) (region.width / bounds.getWidth());
float yScale = (region.height / (line.getAscent() + line.getDescent()));

// Calculate the offset for the text
double x = region.x;
double y = region.y + region.height - (yScale * line.getDescent());
// Create a new transformation, translating the x, y position
// This appears to be trying to place the text at the bottom
// left position of the region, but the problem is, this then gets
// scaled, when means that this translation is no longer the same...   
AffineTransform transformation = AffineTransform.getTranslateInstance(x, y);

// Apply a scale...
if (xScale > yScale)
    transformation.scale(yScale, yScale);
else
    transformation.scale(xScale, xScale);

// Create a new instance of the font using the transformation
graphics.setFont(font.deriveFont(transformation));
// Make it look pretty
graphics.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);

// Render the font within the region...
int centerX = region.width / 2;
int centerY = region.height / 2;
graphics.drawString(text, centerX, centerY - (int) bounds.getHeight());

现在,说了这么多,我很难让它发挥作用。因为您只是根据转换创建一个新的Font,所以抛弃转换会更简单,例如......

// Base font
Font font = new Font("Arial", Font.BOLD, 12);
// Get the fonts metrics
FontMetrics fm = g2d.getFontMetrics(font);

// Calculate the scaling requirements
float xScale = (float) (region.width / fm.stringWidth(text));
float yScale = (region.height / fm.getHeight());

// Determine which access to scale on...
float scale = 0f;
if (xScale > yScale) {
    scale = yScale;
} else {
    scale = xScale;
}

// Create a new font using the scaling facter
g2d.setFont(font.deriveFont(AffineTransform.getScaleInstance(scale, scale)));
// Make it pretty
g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);

// Get the "scaled" metrics
fm = g2d.getFontMetrics();

// Position the text at the left, bottom position of the
// specified region...
int x = 0;
int y = (region.height - fm.getHeight()) + fm.getAscent();
g2d.drawString(text, x, y);

不确定这是否完全正确(您正在寻找什么),但这就是您提供的代码“似乎”试图做的......