如下图所示,在JPanel(500X500)上绘制了一个AttributedString。
AttributedString的FontMetrics.getStringBounds()
给出宽度164.0,如跟踪输出所示。
java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.064453,w=164.0,h=15.09375]
然而,图片显示宽度应为300-400(因为面板的宽度为500)。
您能帮助评论原因和解决方法吗?
import javax.swing.*;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
class MyJPanel extends JPanel {
MyJPanel() {
setPreferredSize(new Dimension(500,500));
}
@Override
public void paintComponent(Graphics gold) {
super.paintComponent(gold);
Graphics2D g = (Graphics2D)gold;
//
AttributedString text = new AttributedString("Bunny rabits and flying ponies");
text.addAttribute(TextAttribute.FONT, new Font("Arial", Font.BOLD, 24), 0, "Bunny rabits".length());
text.addAttribute(TextAttribute.FOREGROUND, Color.RED, 0, "Bunny rabits".length());
text.addAttribute(TextAttribute.FONT, new Font("Arial", Font.BOLD & Font.ITALIC, 32), 17, 17 + "flying ponies".length());
text.addAttribute(TextAttribute.FOREGROUND, Color.BLUE, 17, 17 + "flying ponies".length());
FontMetrics fm = g.getFontMetrics();
System.out.println(fm.getStringBounds(text.getIterator(), 0, text.getIterator().getEndIndex(), g));
g.drawString(text.getIterator(), 50, 50);
//
g.dispose();
}
}
public class MyJFrame extends JFrame {
public static void main(String[] args) {
MyJFrame frame = new MyJFrame();
frame.setContentPane(new MyJPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
答案 0 :(得分:4)
FontMetrics fontMetrics = graphics.getFontMetrics()
根据FontMetrics
对象上当前设置的单个字体返回graphics
个对象。您没有明确更改graphics
使用的字体,因此它使用当前L& F为JPanel
指定的默认字体。
FontMetrics
方法接受"简单" CharacterIterator
(不提供字体信息)而不是AttributedCharacterIterator
(确实如此)。因此fontMetrics.getStringBounds()
只是根据相同大小的单一字体计算文本范围。
使用java.awt.font.TextLayout
使用不同字体和字体大小时,您需要使用AttributedCharacterIterator
来确定正确的界限:
TextLayout textLayout = new TextLayout(
text.getIterator(),
g.getFontRenderContext()
);
Rectangle2D.Float textBounds = ( Rectangle2D.Float ) textLayout.getBounds();
g.drawString( text.getIterator(), 50, 50 );
// lets draw a bounding rect exactly around our text
// to be sure we calculated it properly
g.draw( new Rectangle2D.Float(
50 + textBounds.x, 50 + textBounds.y,
textBounds.width, textBounds.height
) );
答案 1 :(得分:1)
FontMetrics
仅收到CharacterIterator
,并未考虑到它实际上是AttributedCharacterIterator
。您可以使用TextMeasurer
来计算字符串的实际边界。为了进行比较,请在调用drawString
方法后添加此项:
// Compensate for the 50,50 of the drawString position
g.translate(50, 50);
g.setColor(Color.RED);
Rectangle2D wrongBounds = fm.getStringBounds(
text.getIterator(), 0, text.getIterator().getEndIndex(), g);
g.draw(wrongBounds);
System.out.println("wrong: "+wrongBounds);
g.setColor(Color.BLUE);
AttributedCharacterIterator iterator = text.getIterator();
TextMeasurer tm = new TextMeasurer(iterator, g.getFontRenderContext());
Rectangle2D rightBounds = tm.getLayout(0, iterator.getEndIndex()).getBounds();
g.draw(rightBounds);
System.out.println("right: "+rightBounds);
(顺便说一下:不要在g.dispose()
方法中传递给您的Graphics
上致电paintComponent