FontMetrics.getStringBounds for AttributedString 给出错误的结果?

SOU*_*ser 2 java swing awt

如下图所示,在JPanel(500X500)上绘制了一个AttributedString。

FontMetrics.getStringBounds()跟踪输出所示,该 AttributedString 的宽度为 164.0。

java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.064453,w=164.0,h=15.09375]
Run Code Online (Sandbox Code Playgroud)

不过图片建议宽度应该是300-400(因为面板的宽度是500)。

你能帮忙评论原因和解决方法吗?

在此处输入图片说明

我的JFrame.java

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);
    }    
}
Run Code Online (Sandbox Code Playgroud)

Ole*_*hin 5

FontMetrics fontMetrics = graphics.getFontMetrics()返回基于FontMetrics对象上当前设置的单个字体的graphics对象。您没有graphics明确更改使用的字体,因此它使用JPanel当前 L&F指定的默认字体。

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
) );
Run Code Online (Sandbox Code Playgroud)