如何在Java中获得字符的精确边界框

如何在Java中获得字符的精确边界框,java,string,swing,Java,String,Swing,我试图在Java中获得字符的精确边界框。如果我在Swing组件中执行以下操作,是否正常: public class MyFrame extends JFrame { public MyFrame() { super(); this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } private void computeWidth() { String character = "A

我试图在Java中获得字符的精确边界框。如果我在Swing组件中执行以下操作,是否正常:

public class MyFrame extends JFrame {
   public MyFrame() {
     super();
     this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
   }

   private void computeWidth() {
     String character = "A";
     JLabel label = new JLabel();
     Font font = label.getFont();
     font = font.deriveFont(12);

     // method with FontMetrics 
     FontMetrics fontMetrics = this.getFontMetrics(font);
     Rectangle2D recWithMetrics = fontMetrics.getStringBounds(character, this.getGraphics());
     System.out.println("recWithMetrics : " + recWithMetrics);

     // method with GlyphVector outline
     FontRenderContext ctx = new FontRenderContext(new AffineTransform(), true, true);
     GlyphVector gv = font.createGlyphVector(ctx, character);
     Rectangle2D recWithOutline = gv.getOutline().getBounds2D();
     System.out.println("recWithOutline : " + recWithOutline);
   }

   public static void main(String[] args) {
      MyFrame frame = new MyFrame();
      frame.computeWidth();
      frame.setVisible(true);
   }
}

recWithMetrics和recWithOutline的值根本不相同,这是因为使用FontMetrics的方法包括advance吗?

我发现获得文本的形状并使用它“更简单”


我发现获得文本的形状并处理它“更简单”


这是因为使用FontMetrics的方法包括advance吗为什么不显示FontMetrics中的advance值,看看这是否是差异。你是对的,我会检查!!这是因为使用FontMetrics的方法包括advance吗为什么不显示FontMetrics中的advance值,看看这是否是差异。你是对的,我会检查!!因此,在我的测试程序中,第二种情况是使用GlyphVector。我在您的示例中看到大纲是完美的。老实说,我没有仔细查看您的代码。我只知道获取文本的形状对于进行进一步处理非常可靠。这正是我需要的信息。谢谢因此,在我的测试程序中,第二种情况是使用GlyphVector。我在您的示例中看到大纲是完美的。老实说,我没有仔细查看您的代码。我只知道获取文本的形状对于进行进一步处理非常可靠。这正是我需要的信息。谢谢
import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class TextBoundingBox {

    private JComponent ui = null;
    public static String string = "Red outline shows bounds of text";
    public static Font font = new Font(Font.SANS_SERIF, Font.BOLD, 36);

    TextBoundingBox() {
        initUI();
    }

    public void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        ui.add(new JLabel(new ImageIcon(getImage())));
    }

    private static BufferedImage getImage() {
        Shape shape = getShapeOfText(font, string);
        Rectangle2D boundsRectangle = shape.getBounds2D();
        double w = boundsRectangle.getWidth();
        double h = boundsRectangle.getHeight();
        int wBig = (int) (w * 1.1);
        int hBig = (int) (h * 2);
        BufferedImage bi = new BufferedImage(
                wBig, hBig, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, wBig, hBig);

        g.setColor(Color.BLACK);
        g.fill(moveShapeToCenter(shape, wBig, hBig));
        g.setColor(Color.RED);
        g.draw(moveShapeToCenter(boundsRectangle, wBig, hBig));
        g.dispose();

        return bi;
    }

    public static Shape moveShapeToCenter(Shape shape, int w, int h) {
        Rectangle2D b = shape.getBounds2D();
        double xOff = -b.getX() + ((w - b.getWidth()) / 2d);
        double yOff = -b.getY() + ((h - b.getHeight()) / 2d);
        AffineTransform move = AffineTransform.getTranslateInstance(xOff, yOff);
        return move.createTransformedShape(shape);
    }

    public static Shape getShapeOfText(Font font, String msg) {
        BufferedImage bi = new BufferedImage(
                1, 1, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = bi.createGraphics();

        FontRenderContext frc = g.getFontRenderContext();
        GlyphVector gv = font.createGlyphVector(frc, msg);

        return gv.getOutline();
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            TextBoundingBox o = new TextBoundingBox();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}