你如何在 Java 中绘制垂直居中的字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1055851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:57:32  来源:igfitidea点击:

How do you draw a string centered vertically in Java?

javagraphics

提问by Paul Alexander

I know it's a simple concept but I'm struggling with the font metrics. Centering horizontally isn't too hard but vertically seems a bit difficult.

我知道这是一个简单的概念,但我正在努力解决字体指标。水平居中不太难,但垂直居中似乎有点困难。

I've tried using the FontMetrics getAscent, getLeading, getXXXX methods in various combinations but no matter what I've tried the text is always off by a few pixels. Is there a way to measure the exact height of the text so that it is exactly centered.

我尝试过以各种组合使用 FontMetrics getAscent、getLeading、getXXXX 方法,但无论我尝试过什么,文本总是偏离几个像素。有没有办法测量文本的确切高度,使其完全居中。

回答by Lawrence Dol

Note, you doneed to consider precisely what you mean by vertical centering.

请注意,您确实需要准确考虑垂直居中的含义。

Fonts are rendered on a baseline, running along the bottom of the text. The vertical space is allocated as follows:

字体在基线上呈现,沿着文本底部运行。垂直空间分配如下:

---
 ^
 |  leading
 |
 -- 
 ^              Y     Y
 |               Y   Y
 |                Y Y
 |  ascent         Y     y     y 
 |                 Y      y   y
 |                 Y       y y
 -- baseline ______Y________y_________
 |                         y                
 v  descent              yy
 --

The leading is simply the font's recommended space between lines. For the sake of centering vertically between two points, you should ignore leading (it's ledding, BTW, not leeding; in general typography it is/was the lead spacing inserted between lines in a printing plate).

行距只是字体的推荐行间距。为了在两点之间垂直居中,您应该忽略引导(它是引导,顺便说一句,不是引导;在一般排版中,它是/是在印版中的行之间插入的引线间距)。

So for centering the text ascenders and descenders, you want the

因此,为了使文本上升和下降居中,您需要

baseline=(top+((bottom+1-top)/2) - ((ascent + descent)/2) + ascent;

Without the final "+ ascent", you have the position for the top of the font; therefore adding the ascent goes from the top to the baseline.

如果没有最后的“+ ascent”,您将获得字体顶部的位置;因此添加上升是从顶部到基线。

Also, note that the font height should include leading, but some fonts don't include it, and due to rounding differences, the font height may not exactly equal (leading + ascent + descent).

另外请注意,字体高度应该包括前导,但有些字体不包括它,并且由于四舍五入的差异,字体高度可能不完全相等(前导+上升+下降)。

回答by Otto Allmendinger

I found a recipe here.

我在这里找到了一个食谱。

The crucial methods seem to be getStringBounds()and getAscent()

关键的方法似乎是getStringBounds()getAscent()

// Find the size of string s in font f in the current Graphics context g.
FontMetrics fm   = g.getFontMetrics(f);
java.awt.geom.Rectangle2D rect = fm.getStringBounds(s, g);

int textHeight = (int)(rect.getHeight()); 
int textWidth  = (int)(rect.getWidth());
int panelHeight= this.getHeight();
int panelWidth = this.getWidth();

// Center text horizontally and vertically
int x = (panelWidth  - textWidth)  / 2;
int y = (panelHeight - textHeight) / 2  + fm.getAscent();

g.drawString(s, x, y);  // Draw the string.

(note: above code is covered by the MIT Licenseas noted on the page.)

(注意:上面的代码包含在页面上注明的MIT 许可证中。)

回答by Otto Allmendinger

Not sure this helps, but drawString(s, x, y)sets the baselineof the text at y.

不确定这有帮助,但drawString(s, x, y)将文本的基线设置为 y。

I was working with doing some vertical centering and couldn't get the text to look right until I noticed that behavior mentioned in the docs. I was assuming the bottom of the font was at y.

我正在做一些垂直居中,直到我注意到文档中提到的行为才能使文本看起来正确。我假设字体的底部在 y。

For me, the fix was to subtract fm.getDescent()from the y-coordinate.

对我来说,解决方法是fm.getDescent()从 y 坐标中减去。

回答by Mike Scott

Another option is the getBoundsmethod from the TextLayout class.

另一种选择是来自TextLayout 类getBounds方法。

Font f;
// code to create f
String TITLE = "Text to center in a panel.";
FontRenderContext context = g2.getFontRenderContext();

TextLayout txt = new TextLayout(TITLE, f, context);
Rectangle2D bounds = txt.getBounds();
int xString = (int) ((getWidth() - bounds.getWidth()) / 2.0 );
int yString = (int) ((getHeight() + bounds.getHeight()) / 2.0);
// g2 is the graphics object 
g2.setFont(f);
g2.drawString(TITLE, xString, yString);