2009-06-28 6 views
20

간단한 개념이지만 글꼴 메트릭에 어려움을 겪고 있습니다. 수평으로 중심을 맞추는 것은 너무 어렵지 않지만 수직으로는 약간 어려워 보입니다.Java에서 세로로 중심이 지정된 문자열을 어떻게 그리나요?

다양한 조합으로 FontMetrics getAscent, getLeading, getXXXX 메서드를 사용해 보았습니다. 그러나 텍스트를 시도한 것에 관계없이 항상 몇 픽셀 정도 떨어져 있습니다. 텍스트의 정확한 높이를 측정하여 정확히 가운데에 맞출 수있는 방법이 있습니까?

답변

48

주, 당신은 고려해야 할 할 정확하게 수직 센터링의 의미.

글꼴은 텍스트의 하단을 따라 실행되는 기준선에 렌더링됩니다. 수직 공간은 다음과 같이 할당됩니다.

--- 
^ 
| 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; 

합니다; 그러므로 상승을 추가하는 것은 처음부터 끝까지 올라갑니다.

글꼴 높이에는 행간이 포함되어야하지만 일부 글꼴에는 공백이 포함되지 않으며 반올림 차이로 인해 글꼴 높이가 정확히 일치하지 않을 수 있습니다 (leading + ascent + descent).

+0

오우 와우, 완벽한 설명입니다. 고마워요! (또한지도의 설명을 위해, 그것을 몰랐다) – brimborium

+1

당신은 1을 추가하는 이유가 무엇입니까? – Max

+1

@Alex : (바닥 + 1 위)가 높이이기 때문에; 바닥과 꼭대기가 같은 경우 높이가 0이 아닌 1입니다.최종 효과는 중간 점이 n.5 픽셀 인 경우 아래쪽으로 반올림하는 것입니다. –

11

요리법을 찾았습니다 here.

결정적인 방법

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 License에 의해 덮여 위의 페이지에서 언급 한 바와 같이)

+2

예 ... 저는이 개념을 잘 알고 있습니다.하지만 잘못되었습니다. fm.getAscent() 메소드가 문제입니다. 글꼴의 실제 픽셀 상승을보고하지 않고 상단보다 하단에 가까운 텍스트를 표시합니다. –

2

이 정보가 도움이되는지 확실하지 않지만 drawString(s, x, y)의 기본 텍스트을 y로 설정합니다.

세로 센터링을 일부 수행하면서 문서에서 언급 한 동작이 눈에 띄지 않을 때까지 텍스트를 올바르게 볼 수 없었습니다. 나는 글꼴의 바닥이 y라고 가정하고 있었다.

제게는 y 좌표에서 fm.getDescent()을 뺍니다.

1

또 다른 옵션은 TextLayout classgetBounds입니다.

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); 
관련 문제