FontMetrics也有getStringBounds()方法,不仅仅是stringWidth()。
你应该问问自己需要文本宽度干什么。如果是为了通过paintComponent()重写输出,那么你应该在那里测量文本尺寸,这可以确保考虑到所有因素(例如fractionalmetrics、抗锯齿)。此外,您无需考虑释放图形上下文 - 在您的示例中,您肯定需要g.dispose()!
以下示例可在paintComponent()重写中使用,例如对于作为ContentPane的JPanel,它以您指定的字体在组件中心绘制文本,并在其周围绘制一个带有一些距离的矩形,文本完全位于其中心。
然而,文本大小,特别是垂直方向上的大小不精确。更好的解决方案在下面。
不精确解决方案的截图:http://i.imgur.com/vetRjCK.png
更精确的解决方案的截图在下面:http://i.imgur.com/0A0EdCf.png
final int w = getWidth();
final int h = getHeight();
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, w, h);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
final String text = "The Higgs Boson is ...";
g.setColor(Color.ORANGE);
g.setFont(yourFont);
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()));
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
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);
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调用来大致推导文字尺寸,
而是先将文本转换为形状,以得出精确的文本尺寸。
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, w, h);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
final String text = "The Higgs Boson is ...";
g.setColor(Color.ORANGE);
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;
final Shape textShape = gv.getOutline((float) xForShapeCreation, (float) yForShapeCreation + g.getFontMetrics(yourFont).getAscent());
g.fill(textShape);
final Rectangle2D stringBoundsForEverything = textShape.getBounds2D();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
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);
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);
SwingUtilities.computeStringWidth()
。尝试这个技巧:https://dev59.com/qnVC5IYBdhLWcg3wixw0。希望对你有所帮助... - iluxa