首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FontMetrics.getStringBounds for AttributedString给出了错误的结果吗?

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

Stack Overflow用户
提问于 2014-05-31 22:37:34
回答 2查看 1.7K关注 0票数 2

如下图所示,AttributedString是在JPanel (500X500)上绘制的。

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

代码语言:javascript
复制
java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.064453,w=164.0,h=15.09375]

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

你能帮我评论一下原因和解决办法吗?

MyJFrame.java

代码语言:javascript
复制
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);
    }    
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-03 15:42:27

FontMetrics fontMetrics = graphics.getFontMetrics()根据当前设置在graphics对象上的单一字体返回一个FontMetrics对象。您没有显式地更改graphics使用的字体,因此它使用当前L&F为JPanel指定的默认字体。

与边界计算相关的FontMetrics方法接受“简单”CharacterIterator (它不提供字体信息),而不是AttributedCharacterIterator (AttributedCharacterIterator)。因此,fontMetrics.getStringBounds()只需根据相同大小的单一字体计算文本边界。

在使用具有不同字体和字体大小的java.awt.font.TextLayout时,需要使用AttributedCharacterIterator来确定适当的界限:

代码语言:javascript
复制
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
) );
票数 5
EN

Stack Overflow用户

发布于 2014-06-03 15:48:34

FontMetrics只接收一个CharacterIterator,而不考虑它实际上是一个AttributedCharacterIterator。您可以使用TextMeasurer来计算字符串的实际界限。为了进行比较,在调用drawString方法之后添加以下内容:

代码语言:javascript
复制
    // 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);

(和BTW:不要在g.dispose()方法中传递给您的Graphics上调用paintComponent )

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23975076

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档