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

uurity8g  于 2021-06-26  发布在  Java
关注(0)|答案(1)|浏览(363)

我试图在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` 包括预付款?
ercv8c1e

ercv8c1e1#

我发现得到那份工作更简单 Shape 然后用它。

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

相关问题