FontMetrics.getStringBounds的AttributedString给出错误的结果呢? [英] FontMetrics.getStringBounds for AttributedString gives wrong result?

查看:323
本文介绍了FontMetrics.getStringBounds的AttributedString给出错误的结果呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如下面的图所示,构造一个AttributedString画在一个JPanel(500X500)。

FontMetrics.getStringBounds()的AttributedString的给出了164.0的宽度,通过跟踪输出指示。

  java.awt.geom.Rectangle2D中$浮法[X = 0.0,Y = -12.064453,W = 164.0,H = 15.09375]

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

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

MyJFrame.java

 进口的javax.swing *。
进口java.awt中的*。
进口java.awt.font.TextAttribute中;
进口java.text.AttributedString;类MyJPanel继承JPanel {
    MyJPanel(){
        集preferredSize(新尺寸(500,500));
    }    @覆盖
    公共无效的paintComponent(图形金){
        super.paintComponent方法(金);
        Graphics2D的G =(Graphics2D的)金;
        //
        AttributedString文本=新AttributedString(兔子RABiTS基带上和飞行小马);
        text.addAttribute(TextAttribute.FONT,新的字体(宋体,Font.BOLD,24),0,兔子RABiTS基带上。长度());
        text.addAttribute(TextAttribute.FOREGROUND,Color.RED,0,兔子RABiTS基带上。长度());        text.addAttribute(TextAttribute.FONT,新的字体(宋体,Font.BOLD&安培; Font.ITALIC,32),17,17 +飞小马。长度());
        text.addAttribute(TextAttribute.FOREGROUND,Color.BLUE,17,17 +飞小马。长度());        FontMetrics对象FM = g.getFontMetrics();        的System.out.println(fm.getStringBounds(text.getIterator(),0,text.getIterator()为getEndIndex(),G));
        g.drawString(text.getIterator(),50,50);
        //
        g.dispose();
    }
}公共类MyJFrame扩展的JFrame {    公共静态无效的主要(字串[] args){
        MyJFrame帧=新MyJFrame();
        frame.setContentPane(新MyJPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(真);
    }
}


解决方案

FontMetrics对象的FontMetrics = graphics.getFontMetrics()返回的FontMetrics 基于单字体对象目前在图形对象设置。所以它使用当前L&放大器指定为的JP​​anel 默认字体你是不是改变由显卡使用的字体明确; F。

的FontMetrics 有关边界的计算方法接受一个简单的CharacterIterator (不提供字体信息),而不是的的AttributedCharacterIterator (它)。因此, fontMetrics.getStringBounds()简单计算基于相同尺寸的单一字体文本范围。

您需要使用 java.awt.font.TextLayout中的时使用,以确定正确的边界的AttributedCharacterIterator 不同字体和字体大小:

 的TextLayout TextLayout的=新的TextLayout(
        text.getIterator(),
        g.getFontRenderContext()
);
Rectangle2D.Float textBounds =(Rectangle2D.Float)textLayout.getBounds();g.drawString(text.getIterator(),50,50);
//正好可以绘制一个矩形边框围绕我们的文字
//以确保我们正确地计算出它
g.draw(新Rectangle2D.Float(
        50 + textBounds.x,50 + textBounds.y,
        textBounds.width,textBounds.height
));

As shown in the following picture, an AttributedString is drawn on a JPanel (500X500).

The FontMetrics.getStringBounds() of that AttributedString gives a width of 164.0, as indicated by the trace output.

java.awt.geom.Rectangle2D$Float[x=0.0,y=-12.064453,w=164.0,h=15.09375]

However, the picture suggests the width should be 300-400 (because the width of the panel is 500).

Could you help to comment the reason and the workaround ?

MyJFrame.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);
    }    
}

解决方案

FontMetrics fontMetrics = graphics.getFontMetrics() returns a FontMetrics object based on the single font currently set on the graphics object. You are not changing the font used by graphics explicitly so it uses the default font designated for JPanel by the current L&F.

FontMetrics methods related to bounds calculation accept a "simple" CharacterIterator (which does not provide font information) instead of AttributedCharacterIterator (which does). Hence fontMetrics.getStringBounds() simply calculates the text bounds based on the single font of the same size.

You need to use java.awt.font.TextLayout to determine the proper bounds when using AttributedCharacterIterator with different fonts and font sizes:

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
) );

这篇关于FontMetrics.getStringBounds的AttributedString给出错误的结果呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆