Подтвердить что ты не робот

Как вы нарисовываете вертикальную строку по вертикали в Java?

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

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

4b9b3361

Ответ 1

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

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

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

Ведущим является просто рекомендуемое шрифтом место между строками. Для центрирования по вертикали между двумя точками вы должны игнорировать ведущие (это ведение, BTW, не leeding, в общей типографии это/было расстоянием между строками, вставленным между строками в печатной пластине).

Итак, для центрирования текстовых подрастеров и descenders вы хотите

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

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

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

Ответ 2

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

Ключевыми методами являются 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, как указано на странице.)

Ответ 3

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

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

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

Ответ 4

Другим вариантом является метод 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);