我使用FontMetrics.getHeight()
來獲取字符串的高度,但它給了我一個錯誤的值,切斷了字符串字符的下移。有更好的功能可以使用嗎?如何在Java中獲得真正的字符串高度?
回答
下getStringBounds()
方法是基於GlyphVector
當前Graphics2D
字體,它非常適用於文本的一個線串:
public class StringBoundsPanel extends JPanel
{
public StringBoundsPanel()
{
setBackground(Color.white);
setPreferredSize(new Dimension(400, 247));
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// must be called before getStringBounds()
g2.setFont(getDesiredFont());
String str = "My Text";
float x = 140, y = 128;
Rectangle bounds = getStringBounds(g2, str, x, y);
g2.setColor(Color.red);
g2.drawString(str, x, y);
g2.setColor(Color.blue);
g2.draw(bounds);
g2.dispose();
}
private Rectangle getStringBounds(Graphics2D g2, String str,
float x, float y)
{
FontRenderContext frc = g2.getFontRenderContext();
GlyphVector gv = g2.getFont().createGlyphVector(frc, str);
return gv.getPixelBounds(null, x, y);
}
private Font getDesiredFont()
{
return new Font(Font.SANS_SERIF, Font.BOLD, 28);
}
private void startUI()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
final StringBoundsPanel tb = new StringBoundsPanel();
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
tb.startUI();
}
});
}
}
請注意,我省略了清晰的進口。
其結果是:
是什麼讓你覺得它返回錯誤的值?你很可能期望它返回的內容與規範不符。請注意,如果字體中的某些字形超出或低於這些值,那就很好了。
getMaxDescent()
和getMaxAscent()
應該告訴你字體中任何字形的那些字段的絕對最大值。
如果您想知道特定字符串的指標,那麼您一定要致電getLineMetrics()
。
getHeight()
不能切斷字符串的下行,只能繪製字符串可以做到這一點。您正在使用從getHeight
返回的高度以某種方式繪製字符串,並且可能是濫用了高度。例如,如果你在一個盒子,是的getHeight的底部位置字符串的起點()高,那麼你的文本的基線將坐在箱子的底部邊緣,並且極有可能緣將被裁剪。
文字幾何是一個複雜的話題,注入奇異的歷史文物。正如其他人所建議的那樣,請使用getAscent
和getDescent
嘗試在您的框中正確定位基線。
我最近寫下面的代碼作爲我所需字體的特定範圍的像素完美高度測量值(例如:所有較低的字符,或所有的數字)。
如果需要更快的代碼(我擁有for循環)我會建議在啓動時運行一次它獲得的所有值(例如,從1到100)在一個數組,然後使用數組來代替。
該代碼基本上將輸入字符串中的所有字符繪製在250x250位圖上重疊的相同位置(如果需要增加或減少),它將從頂部開始尋找像素,然後從底部開始,然後返回找到的最大高度。它適用於普通字符串,即使它是爲字符範圍而設計的。這意味着在評估常規字符串時會有一些冗餘,因爲某些字符會重複。因此,如果您的輸入字符串超過字母數(26),請使用'tRange'輸入:「abcd ... z」和其他可能使用的字符。它更快。
希望有所幫助。
public int getFontPixelHeight(float inSize, Paint sourcePaint, String tRange)
{
// It is assumed that the font is already set in the sourcePaint
int bW = 250, bH = 250; // bitmap's width and height
int firstContact = -1, lastContact = -2; // Used when scanning the pixel rows. Initial values are set so that if no pixels found, the returned result is zero.
int tX = (int)(bW - inSize)/2, tY = (int)(bH - inSize)/2; // Used for a rough centering of the displayed characters
int tSum = 0;
// Preserve the original paint attributes
float oldSize = sourcePaint.getTextSize();
int oldColor = sourcePaint.getColor();
// Set the size/color
sourcePaint.setTextSize(inSize); sourcePaint.setColor(Color.WHITE);
// Create the temporary bitmap/canvas
Bitmap.Config bConf = Bitmap.Config.ARGB_8888;
Bitmap hld = Bitmap.createBitmap(250, 250, bConf);
Canvas canv = new Canvas(hld);
for (int i = 0; i < bH; i++)
{
for (int j = 0; j < bW; j++)
{
hld.setPixel(j, i, 0); // Zero all pixel values. This might seem redundant, but I am not quite sure that creating a blank bitmap means the pixel color value is indeed zero, and I need them to be zero so the addition performed below is correct.
}
}
// Display all characters overlapping at the same position
for (int i = 0; i < tRange.length(); i++)
{
canv.drawText("" + tRange.charAt(i), tX, tY, sourcePaint);
}
for (int i = 0; i < bH; i++)
{
for (int j = 0; j < bW; j++)
{
tSum = tSum + hld.getPixel(j, i);
}
if (tSum > 0) // If we found at least a pixel, save row index and exit loop
{
firstContact = i;
tSum = 0; // Reset
break;
}
}
for (int i = bH - 1; i > 0 ; i--)
{
for (int j = 0; j < bW; j++)
{
tSum = tSum + hld.getPixel(j, i);
}
if (tSum > 0) // If we found at least a pixel, save row index and exit loop
{
lastContact = i;
break;
}
}
// Restore the initial attributes, just in case the paint was passed byRef somehow
sourcePaint.setTextSize(oldSize);
sourcePaint.setColor(oldColor);
return lastContact - firstContact + 1;
}
- 1. 如何獲得java中字符串/字符的高度?
- 2. 如何獲得在java中的字符串的寬度
- 3. 如何獲得真正的屏幕高度和寬度?
- 4. 如何獲得TextBox的真實高度?
- 5. 如何獲得字符串的真實長度?
- 6. 如何獲得真正的iframe身高?
- 7. C#:如何獲得字符串中的字符串的長度[]
- 8. 如何獲得字符串的寬度
- 9. 如何獲得字符串的長度[] []
- 10. 如何使用JQuery獲得真正的圖像高度?
- 11. 如何獲得給定字符串下行的高度?
- 12. 使用Javascript - 獲得真正的字母寬度和高度(無行高)
- 13. 如何在JavaScript中獲得DIV對象的真實高度?
- 14. 如何在PostScript中獲取字符串的高度指標?
- 15. Java:如何從JcomboBox獲得字符串
- 16. 在Java中獲得雙倍字符串
- 17. 如何在Python中獲得numpy數組的真正維度?
- 18. 如何獲得子字符串在iPhone中的字符串?
- 19. 如何真正在Android中獲取導航欄高度
- 20. 如何獲得字符串中的度符號?
- 21. 如何獲得雙引號之間的字符串,字符串中的Java中
- 22. 如何在java中獲得真正的unix時間戳
- 23. 如何在Java 5中獲得今天的字符串?
- 24. 如何獲得在括號中的字符串與Java數組
- 25. 如何獲得價值高達定字符串的一定長度在PHP
- 26. 如何在swift中獲得正確的字符串數組?
- 27. 如何獲取字符串的像素寬度和高度?
- 28. 在java中如何從字符串獲得子串直到字符c?
- 29. 如何在Swift iOS8中正確獲取字符串的寬度?
- 30. 如何嵌入真正的「$」字符在bash字符串
@nierito偉大的答案和偉大的演示呢!根據你所說的,我已經盡力縮短你的代碼(假設一個定義了`Font`,並從中得到了`FontMetrics`)。它的工作原理相當不錯。 `字體。createGlyphVector(fontMetrics.getFontRenderContext(),text).getVisualBounds()。getHeight();` – 2013-01-30 23:13:34