如何从JAVA中的FontMetrics获取正确的String宽度 [英] How to get the correct String width from FontMetrics in JAVA

查看:3172
本文介绍了如何从JAVA中的FontMetrics获取正确的String宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 FontMetrics 对象上的 stringWidth(str)方法计算字符串的宽度。此方法仅为我提供基线上从起点到终点的宽度。不是字符串的总宽度。

I calculate the width of a string by using the stringWidth("str") method on the FontMetrics object. This method only gives me the width from the starting point to the ending point on the baseline. Not the overall width of the string.

关于如何计算总宽度的任何想法?

Any ideas on how to calculate the overall width?

大多数文档说我不能通过在字符串中添加每个字符的宽度来依赖结果。
以下是我的代码:

Most documentation says that I can't rely on the result by adding the width of each char in the string. Here is my code until now:

BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
FontMetrics fm = g.getFontMetrics(new Font("Arial", Font.PLAIN, 6));
int width = fm.stringWidth("Product name");


推荐答案

FontMetrics还有getStringBounds(),而不仅仅是stringWidth( )。

FontMetrics also has getStringBounds(), not just stringWidth().

你应该问问自己你需要什么样的文字宽度。如果它是通过例如输出paintComponent()覆盖,然后你应该测量那里的文本维度,这确保考虑所有因素(例如,分数计,抗锯齿)。此外,您不必考虑处理图形上下文 - 在您的示例中,您必须,它需要g.dispose()!

You should ask yourself what you need the text width for. If it's for output via e.g. a paintComponent() override, then you should measure the text dimensions there, which makes sure that all factors (e.g. fractionalmetrics, antialiasing) are taken into consideration. Also, you don't have to think about disposing the graphics context - which in your example, you definitely have to, it needs g.dispose()!

以下用于paintComponent()覆盖的示例,例如对于你用作ContentPane的JPanel,用你给出的字体在组件的中心绘制一个文本,并在它周围画一个矩形,距离很近,文本完全在它的中心。

The following example for use in a paintComponent() override, e.g. for the JPanel you're using as your ContentPane, draws a text at the center of the component in a font given by you and draws a rectangle around it with some distance, the text being perfectly in its center.

但是,文字大小(尤其是垂直方向)不精确。更好的解决方案是进一步下降。

The text size, especially vertically, is not precise, however. A better solution is further down.

这种不精确的解决方案的屏幕截图: http://i.imgur.com/vetRjCK.png

Screenshot of this imprecise solution: http://i.imgur.com/vetRjCK.png

精确解决方案的屏幕截图: http://i.imgur.com/0A0EdCf.png

Screenshot of precise solution further down: http://i.imgur.com/0A0EdCf.png

final int w = getWidth();
final int h = getHeight();

// CLEAR BACKGROUND
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, w, h);

// ACTIVATE ANTIALIASING AND FRACTIONAL METRICS
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

// PREPARE TEXT, COLOR, FONT
final String text = "The Higgs Boson is ...";
g.setColor(Color.ORANGE);
g.setFont(yourFont);

// PREPARE COORDINATES, AND DRAW TEXT
final FontMetrics fm = g.getFontMetrics();
final Rectangle2D stringBounds = fm.getStringBounds(text, g);
final double x = (w - stringBounds.getWidth()) / 2d;
final double y = (h - stringBounds.getHeight()) / 2d;
g.drawString(text, (int) x, (int) (y + fm.getAscent()));

// TURN OFF ANTIALIASING FOR HIGHER VISUAL PRECISION OF THE LINES
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

// DRAW RECTANGLE BORDER
final double borderDistance = 10d;
final Shape borderRect = new Rectangle2D.Double(x - borderDistance * 2, y - borderDistance, stringBounds.getWidth() + borderDistance * 4, stringBounds.getHeight() + borderDistance * 2);
g.setStroke(new BasicStroke(3f));
g.draw(borderRect);

// DRAW THIN TIGHT RECTANGLE BORDER
final Shape borderRectTight = new Rectangle2D.Double(x, y , stringBounds.getWidth(), stringBounds.getHeight());
g.setStroke(new BasicStroke(1f));
g.setColor(Color.GRAY);
g.draw(borderRectTight);

以下解决方案在结构上与上面类似,但不是使用FontMetrics调用来松散地派生文本尺寸,通过首先将文本转换为形状来获得精确的文字尺寸

The following solution is structurally just like the above, but instead of using FontMetrics-calls to loosely derive the text dimensions, it derives the precise text dimensions by converting the text into a Shape first.

// CLEAR BACKGROUND
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, w, h);

// ACTIVATE ANTIALIASING AND FRACTIONAL METRICS
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

// PREPARE TEXT, COLOR
final String text = "The Higgs Boson is ...";
g.setColor(Color.ORANGE);

// CREATE GLYPHVECTOR FROM TEXT, CREATE PRELIMINARY SHAPE FOR COORDINATE CALCULATION, CALC COORDINATES
final GlyphVector gv = yourFont.createGlyphVector(g.getFontRenderContext(), text);
final Rectangle2D stringBoundsForPosition = gv.getOutline().getBounds2D();
final double xForShapeCreation = (w - stringBoundsForPosition.getWidth()) / 2d;
final double yForShapeCreation = (h - stringBoundsForPosition.getHeight()) / 2d;

// DERIVE SHAPE AGAIN, THIS TIME IN THE RIGHT PLACE (IT'S NOT THE ONLY POSSIBLE METHOD.)
final Shape textShape = gv.getOutline((float) xForShapeCreation, (float) yForShapeCreation + g.getFontMetrics(yourFont).getAscent());
g.fill(textShape);

// GET PRECISE SHAPE BOUNDS, TURN OFF ANTIALIASING FOR HIGHER VISUAL PRECISION OF THE LINES
final Rectangle2D stringBoundsForEverything = textShape.getBounds2D();// JavaDocs: "Returns a high precision [...] bounding box of the Shape [...] guarantee [...] that the Shape lies entirely within the indicated Rectangle2D."
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

// DRAW RECTANGLE BORDER
final double borderDistance = 10d;
final Shape borderRect = new Rectangle2D.Double(stringBoundsForEverything.getX() - borderDistance * 2, stringBoundsForEverything.getY() - borderDistance, stringBoundsForEverything.getWidth() + borderDistance * 4, stringBoundsForEverything.getHeight() + borderDistance * 2);
g.setStroke(new BasicStroke(3f));
g.draw(borderRect);

// DRAW THIN TIGHT RECTANGLE BORDER
final Shape borderRectTight = new Rectangle2D.Double(stringBoundsForEverything.getX(), stringBoundsForEverything.getY(), stringBoundsForEverything.getWidth(), stringBoundsForEverything.getHeight());
g.setStroke(new BasicStroke(1f));
g.setColor(Color.GRAY);
g.draw(borderRectTight);

这篇关于如何从JAVA中的FontMetrics获取正确的String宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆