Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JAVA中从FontMetrics获取正确的字符串宽度_Java_String - Fatal编程技术网

如何在JAVA中从FontMetrics获取正确的字符串宽度

如何在JAVA中从FontMetrics获取正确的字符串宽度,java,string,Java,String,我使用FontMetrics对象上的stringWidth(“str”)方法计算字符串的宽度。此方法仅给出基线上从起点到终点的宽度。不是字符串的总宽度 关于如何计算总宽度有什么想法吗 大多数文档都说,我不能通过在字符串中添加每个字符的宽度来依赖结果。 以下是我到目前为止的代码: BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphic

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

关于如何计算总宽度有什么想法吗

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

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");

您需要一个图形对象

graphics.setFont(font)


int lenghtgraphics.getFontMetrics(graphics.getFont()).stringWidth(value)

几年前,我构建了一个xml呈现组件,并且非常依赖它

SwingUtilities.computeStringWidth(fontMetrics,字符串)

我从正在测量字符串的组件中获取字体度量


myComponent.getFontMetrics(myComponent.getFont())

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

你应该问问自己,你需要什么样的文本宽度。如果是通过paintComponent()覆盖进行输出,则应测量文本尺寸,以确保考虑所有因素(例如分馏矩阵、抗锯齿)。另外,您不必考虑处理图形上下文-在您的示例中,您肯定必须这样做,它需要g.dispose()

下面的示例用于paintComponent()覆盖,例如,对于用作ContentPane的JPanel,使用您指定的字体在组件的中心绘制一个文本,并在其周围绘制一个有一定距离的矩形,文本完全位于其中心

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

此不精确解决方案的屏幕截图:

进一步向下精确解决方案的屏幕截图:

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

// 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);

祝你好运我曾经在这上面浪费了3天,尝试了14种技术,95%的时间都能用上。。。我试着避开秋千since@iluxa嗯。谢谢:-)。。95%对我来说没问题。你能告诉我你做了什么吗?你用宽度做什么?您还可以尝试使用其他方法。例如,getStringBounds。您也可以尝试使用GlyphVector,而不是绘制字符串(我假设您最终会这样做),这是一种形状表示,并为您提供了许多其他选项。我个人建议尝试使用GlyphVector。它能做的事情有很多是用FontMetrics和drawString做不到的:哥们,我希望我记得。。。请尝试
SwingUtilities.computeTestRingWidth()
。尝试以下技巧:。希望你能有所收获…谢谢你在Dreamspace President发表的评论。但是自从我在一年多前提出这个问题以来,这个系统现在已经在客户那里运行了。这个解决方案不是100%好,但我们可以接受。。
// 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);