Как вы рисуете строку по центру в Java? - PullRequest
20 голосов
/ 29 июня 2009

Я знаю, что это простая концепция, но я борюсь с метриками шрифта. Центрирование по горизонтали не слишком сложно, но по вертикали кажется немного сложным.

Я пытался использовать методы FontMetrics getAscent, getLeading, getXXXX в различных комбинациях, но независимо от того, что я пробовал, текст всегда на несколько пикселей меньше. Есть ли способ измерить точную высоту текста так, чтобы он был точно по центру.

Ответы [ 4 ]

48 голосов
/ 29 июня 2009

Обратите внимание, вам нужно нужно точно учитывать, что вы подразумеваете под вертикальным центрированием.

Шрифты отображаются на базовой линии, проходящей вдоль нижней части текста. Вертикальное пространство выделяется следующим образом:

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

Начальная буква - это просто рекомендуемое расстояние между строками шрифта. Ради центрирования по вертикали между двумя точками следует игнорировать ведение (это ведение, кстати, не прохождение; в обычной типографии это / было расстояние между отведениями, вставленное между линиями в печатной форме).

Так что для центрирования текста по возрастанию и спуску, вы хотите

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

Без окончательного «+ подъема» у вас есть позиция для верхней части шрифта; поэтому добавление восхождения идет от вершины к базовой линии.

Кроме того, обратите внимание, что высота шрифта должна включать начальные, но некоторые шрифты не включают его, и из-за различий в округлении высота шрифта может не совпадать (начальные + подъем + спуск).

11 голосов
/ 29 июня 2009

Я нашел рецепт здесь .

Важнейшими методами являются 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.

(примечание: указанный выше код распространяется на Лицензия MIT , как указано на странице.)

2 голосов
/ 16 сентября 2009

Не уверен, что это помогает, но drawString(s, x, y) устанавливает базовую линию текста на y.

Я работал с некоторым вертикальным центрированием и не мог заставить текст выглядеть правильно, пока не заметил это поведение, упомянутое в документах. Я предполагал, что нижняя часть шрифта была у.

Для меня исправлением было вычесть fm.getDescent() из координаты y.

1 голос
/ 05 апреля 2012

Другой вариант - метод getBounds из класса TextLayout .

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...