2013-10-25 24 views
2

我使用FontMetrics對象上的stringWidth("str")方法計算字符串的寬度。此方法僅給出從基線的起點到終點的寬度。不是字符串的整體寬度。如何從JAVA中的FontMetrics獲取正確的字符串寬度

有關如何計算總寬度的任何想法?

大多數文檔說,我不能依靠添加字符串中每個字符的寬度的結果。 這裏是我的代碼,直到現在:

BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); 
Graphics2D g = image.createGraphics(); 
FontMetrics fm = g.getFontMetrics(new Font("Arial", Font.PLAIN, 6)); 
int width = fm.stringWidth("Product name"); 
+0

祝你好運!我曾經浪費了3天的時間,嘗試了14種技巧,並且在95%的時間內完成了它的工作......自從 – iluxa

+0

@iluxa嗯以來,我試圖從Swing中清除。謝謝:-) .. 95%對我來說可以。你能告訴我,你做了什麼? –

+0

你在做什麼寬度?還有其他方法可以嘗試使用。例如getStringBounds。您也可以嘗試使用GlyphVector而不是繪製字符串(我假設您最終會這樣做),這是一種Shape表示形式,併爲您提供了很多其他選項。 – Radiodef

回答

0

你需要一個圖形對象。

graphics.setFont(font);

int lenghtgraphics.getFontMetrics(graphics.getFont()).stringWidth(value);

0

我建立了一個XML渲染部件在幾年前,並非常依賴

SwingUtilities.computeStringWidth(fontMetrics, string);

我從我是該組件的字體規格測量的字符串。

myComponent.getFontMetrics(myComponent.getFont());

5

的FontMetrics也有getStringBounds(),而不僅僅是stringWidth()。

你應該問自己你需要什麼文字寬度。如果它是通過例如輸出的話一個paintComponent()覆蓋,那麼你應該測量那裏的文本尺寸,這可以確保考慮所有因素(例如分數度量,反鋸齒)。此外,你不必考慮處理圖形上下文 - 在你的例子中,你肯定必須這樣做,它需要g.dispose()!

以下用於paintComponent()覆蓋的示例,例如,對於您用作ContentPane的JPanel,按照您提供的字體在組件中心繪製文本,並在距離周圍繪製矩形,文本完全位於其中心。

但是,文本大小,特別是垂直方向,是不準確。更好的解決方案是進一步下降。

截圖這個不精確解決方案:http://i.imgur.com/vetRjCK.png

截圖精確的解決方案的進一步下跌:http://i.imgur.com/0A0EdCf.png

final int w = getWidth(); 
final int h = getHeight(); 

// CLEAR BACKGROUND 
g.setColor(Color.DARK_GRAY); 
g.fillRect(0, 0, w, h); 

// ACTIVATE ANTIALIASING AND FRACTIONAL METRICS 
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 

// PREPARE TEXT, COLOR, FONT 
final String text = "The Higgs Boson is ..."; 
g.setColor(Color.ORANGE); 
g.setFont(yourFont); 

// PREPARE COORDINATES, AND DRAW TEXT 
final FontMetrics fm = g.getFontMetrics(); 
final Rectangle2D stringBounds = fm.getStringBounds(text, g); 
final double x = (w - stringBounds.getWidth())/2d; 
final double y = (h - stringBounds.getHeight())/2d; 
g.drawString(text, (int) x, (int) (y + fm.getAscent())); 

// TURN OFF ANTIALIASING FOR HIGHER VISUAL PRECISION OF THE LINES 
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); 

// DRAW RECTANGLE BORDER 
final double borderDistance = 10d; 
final Shape borderRect = new Rectangle2D.Double(x - borderDistance * 2, y - borderDistance, stringBounds.getWidth() + borderDistance * 4, stringBounds.getHeight() + borderDistance * 2); 
g.setStroke(new BasicStroke(3f)); 
g.draw(borderRect); 

// DRAW THIN TIGHT RECTANGLE BORDER 
final Shape borderRectTight = new Rectangle2D.Double(x, y , stringBounds.getWidth(), stringBounds.getHeight()); 
g.setStroke(new BasicStroke(1f)); 
g.setColor(Color.GRAY); 
g.draw(borderRectTight); 

以下解決方案在結構上就像上面,但不是使用的FontMetrics通話鬆散地推導文本尺寸,它通過首先將文本轉換爲Shape來導出精確的文本尺寸

// CLEAR BACKGROUND 
g.setColor(Color.DARK_GRAY); 
g.fillRect(0, 0, w, h); 

// ACTIVATE ANTIALIASING AND FRACTIONAL METRICS 
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 

// PREPARE TEXT, COLOR 
final String text = "The Higgs Boson is ..."; 
g.setColor(Color.ORANGE); 

// CREATE GLYPHVECTOR FROM TEXT, CREATE PRELIMINARY SHAPE FOR COORDINATE CALCULATION, CALC COORDINATES 
final GlyphVector gv = yourFont.createGlyphVector(g.getFontRenderContext(), text); 
final Rectangle2D stringBoundsForPosition = gv.getOutline().getBounds2D(); 
final double xForShapeCreation = (w - stringBoundsForPosition.getWidth())/2d; 
final double yForShapeCreation = (h - stringBoundsForPosition.getHeight())/2d; 

// DERIVE SHAPE AGAIN, THIS TIME IN THE RIGHT PLACE (IT'S NOT THE ONLY POSSIBLE METHOD.) 
final Shape textShape = gv.getOutline((float) xForShapeCreation, (float) yForShapeCreation + g.getFontMetrics(yourFont).getAscent()); 
g.fill(textShape); 

// GET PRECISE SHAPE BOUNDS, TURN OFF ANTIALIASING FOR HIGHER VISUAL PRECISION OF THE LINES 
final Rectangle2D stringBoundsForEverything = textShape.getBounds2D();// JavaDocs: "Returns a high precision [...] bounding box of the Shape [...] guarantee [...] that the Shape lies entirely within the indicated Rectangle2D." 
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); 

// DRAW RECTANGLE BORDER 
final double borderDistance = 10d; 
final Shape borderRect = new Rectangle2D.Double(stringBoundsForEverything.getX() - borderDistance * 2, stringBoundsForEverything.getY() - borderDistance, stringBoundsForEverything.getWidth() + borderDistance * 4, stringBoundsForEverything.getHeight() + borderDistance * 2); 
g.setStroke(new BasicStroke(3f)); 
g.draw(borderRect); 

// DRAW THIN TIGHT RECTANGLE BORDER 
final Shape borderRectTight = new Rectangle2D.Double(stringBoundsForEverything.getX(), stringBoundsForEverything.getY(), stringBoundsForEverything.getWidth(), stringBoundsForEverything.getHeight()); 
g.setStroke(new BasicStroke(1f)); 
g.setColor(Color.GRAY); 
g.draw(borderRectTight); 
+1

感謝您的評論@Dreamspace總裁。但是自從我在1年多前提出這個問題以來,系統現在正在運行在客戶身上。解決方案不是100%好,但我們可以與它一起生活.. –

相關問題