3

我熟悉如何使用各种 FontMetrics 函数将文本垂直、水平等居中。但是,我正在寻找一个支持在相对于字符串的给定 xy 位置绘制文本的库(例如,我希望字符串的中心位于 x,y,或者我希望它的右上角在这里,等等。 )

我发现了 JCommon及其声称可以做到这一点的文本锚点,但是我无法让它工作,并且论坛迄今为止没有响应

我知道我可以自己编写所有实用程序函数,但如果可能的话,我想避免重新发明轮子。

4

4 回答 4

1

我不知道有任何库,但我猜如果你自己做,你只会使用 Graphics.translate() 将文本翻译到相对位置。

于 2010-02-17T06:33:34.667 回答
1

最终不得不自己做。代码如下:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestFontLayout extends JPanel {

    public enum AnchorPoint{
        UPPER_LEFT,
        TOP_CENTER,
        UPPER_RIGHT,
        RIGHT_CENTER,
        LOWER_RIGHT,
        BOTTOM_CENTER,
        LOWER_LEFT,
        LEFT_CENTER,
        CENTER
    };

    public void drawText(TextLayout text, AnchorPoint point, Graphics2D g2, float x, float y) {
        float translationX = 0.0f;
        float translationY = 0.0f;

        Rectangle2D bounds = text.getBounds();
        float midYOffset = (float) bounds.getHeight()/2;
        float midXOffset = (float) -bounds.getWidth()/2;

        float topYOffset = (float) bounds.getHeight();
        float bottomYOffset = 0.0f;

        float leftXOffset = 0.0f;
        float rightXOffset = (float) -bounds.getWidth();

        // Adjust x values
        switch (point) {
            // Left
            case UPPER_LEFT:
            case LOWER_LEFT:
            case LEFT_CENTER:
                translationX = leftXOffset;
                break;
                // Mid
            case TOP_CENTER:
            case BOTTOM_CENTER:
            case CENTER:
                translationX = midXOffset;
                break;
            // Right
            case UPPER_RIGHT:
            case RIGHT_CENTER:
            case LOWER_RIGHT:
                translationX = rightXOffset;
        }

        // Adjust y values
        switch (point) {
            // Top
            case UPPER_LEFT:
            case UPPER_RIGHT:
            case TOP_CENTER:
                translationY = topYOffset;
                break;
            // Mid
            case LEFT_CENTER:
            case CENTER:
            case RIGHT_CENTER:
                translationY = midYOffset;
                break;
            // Bottom
            case LOWER_LEFT:
            case BOTTOM_CENTER:
            case LOWER_RIGHT:
                translationY = bottomYOffset;
        }

        text.draw(g2, x + translationX, y + translationY);

    }

    public TestFontLayout() {
        super();
        setPreferredSize(new Dimension(400,400));
    }
    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        // Ensure that the default painting occurs
        super.paintComponent(g);

        Point2D loc = new Point2D.Double(getWidth()/2,getHeight()/2);
        Font font = Font.decode("Helvetica");
        FontRenderContext frc = g2.getFontRenderContext();
        TextLayout layout = new TextLayout("This is a string", font, frc);

        g2.setColor(Color.RED);
        g2.drawRect(getWidth()/2, getHeight()/2, 1,1);

        g2.setColor(Color.PINK);
        drawText(layout, AnchorPoint.UPPER_LEFT, g2, 0, 0);

        g2.setColor(Color.BLUE);
        drawText(layout, AnchorPoint.TOP_CENTER, g2, getWidth()/2, 0);

        g2.setColor(Color.ORANGE);
        drawText(layout, AnchorPoint.UPPER_RIGHT, g2, getWidth(), 0);

        g2.setColor(Color.CYAN);
        drawText(layout, AnchorPoint.RIGHT_CENTER, g2, getWidth(), getHeight()/2);

        g2.setColor(Color.ORANGE);
        drawText(layout, AnchorPoint.LOWER_RIGHT, g2, getWidth(), getHeight());

        g2.setColor(Color.BLACK);
        drawText(layout, AnchorPoint.BOTTOM_CENTER, g2, getWidth()/2, getHeight());


        g2.setColor(Color.YELLOW);
        drawText(layout, AnchorPoint.LOWER_LEFT, g2, 0, getHeight());

        g2.setColor(Color.DARK_GRAY);
        drawText(layout, AnchorPoint.LEFT_CENTER, g2, 0, getHeight()/2);


        g2.setColor(Color.MAGENTA);
        drawText(layout, AnchorPoint.CENTER, g2, getWidth()/2, getHeight()/2);
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame("");
        frame.add(new TestFontLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

    }
}

替代文字 http://grab.by/2WlM

于 2010-03-09T19:48:37.503 回答
0

你可能会看TextLayout。和方法可以draw()简化getBounds()编码。

于 2010-02-18T04:09:26.567 回答
0

我发现I82MuchTestFontLayout的代码非常有用,谢谢。垂直对齐有一个小错误。我的解决方法是使用而不是用于“偏移”计算。此外,该方法已修改为返回一个自定义类以提供绘制文本的角坐标,以便下一个绘图可以使用 Box 角来对齐更多文本。这是我的代码版本。bounds.getY()bounds.getHeight()drawText(...)Box

import static java.awt.Color.BLACK;
import static java.awt.Color.BLUE;
import static java.awt.Color.CYAN;
import static java.awt.Color.DARK_GRAY;
import static java.awt.Color.MAGENTA;
import static java.awt.Color.ORANGE;
import static java.awt.Color.PINK;
import static java.awt.Color.RED;
import static java.awt.Color.YELLOW;
import static java.awt.Font.PLAIN;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestFontLayout2 extends JPanel
{
    private static final long serialVersionUID = 1L;

    public enum Anchor
    {
        UPPER_LEFT,
        UPPER_CENTER,
        UPPER_RIGHT,
        MIDDLE_LEFT,
        MIDDLE_CENTER,
        MIDDLE_RIGHT,
        LOWER_LEFT,
        LOWER_CENTER,
        LOWER_RIGHT
    };

    public static Box drawText(Graphics2D g2d, String text, Anchor point, float xpos, float ypos)
    {
        return drawText(g2d, new TextLayout(text, g2d.getFont(), g2d.getFontRenderContext()), point, xpos, ypos);
    }
    
    public static Box drawText(Graphics2D g2d, String text, Anchor point, float xpos, float ypos, Font font)
    {
        return drawText(g2d, new TextLayout(text, font, g2d.getFontRenderContext()), point, xpos, ypos);
    }
    
    public static Box drawText(Graphics2D g2d, TextLayout text, Anchor anchor, float xpos, float ypos)
    {
        Rectangle2D bounds = text.getBounds();

        float xOffsetLeft = 0.0f;
        float xOffsetRight = (float) -bounds.getWidth();
        float xOffsetCenter = (float) -bounds.getWidth() / 2.0f;
        
        // Bounds.getY() is the (negative) offset between the baseline and the top of the text.
        // Bounds.getHeight() is the distance above plus the distance below the text baseline.
        float yOffsetTop = (float) bounds.getY();
        float yOffsetBottom = (float) (bounds.getHeight()+bounds.getY());
        float yOffsetMiddle = (float) (-bounds.getHeight()) / 2.0f;
        
        float xOffset = 0.0f;
        float yOffset = 0.0f;

        // Adjust x values
        switch (anchor)
        {
            // Left
            case UPPER_LEFT:
            case MIDDLE_LEFT:
            case LOWER_LEFT:
                xOffset = xOffsetLeft;
                break;
            // Center
            case UPPER_CENTER:
            case MIDDLE_CENTER:
            case LOWER_CENTER:
                xOffset = xOffsetCenter;
                break;
            // Right
            case UPPER_RIGHT:
            case MIDDLE_RIGHT:
            case LOWER_RIGHT:
                xOffset = xOffsetRight;
                break;
        }

        // Adjust y values
        switch (anchor)
        {
            // Top
            case UPPER_LEFT:
            case UPPER_CENTER:
            case UPPER_RIGHT:
                yOffset = yOffsetTop;
                break;
            // Middle
            case MIDDLE_LEFT:
            case MIDDLE_CENTER:
            case MIDDLE_RIGHT:
                yOffset = yOffsetMiddle;
                break;
            // Bottom
            case LOWER_LEFT:
            case LOWER_CENTER:
            case LOWER_RIGHT:
                yOffset = yOffsetBottom;
                break;
        }
        
        // Draw text at baseline position.
        float xbase = xpos + xOffset;
        float ybase = ypos - yOffset;
        text.draw(g2d, xbase, ybase);
        
        // Enclose text within a box.
        int xrect = rnd(xbase + bounds.getX());
        int yrect = rnd(ybase + bounds.getY());
        int wrect = rnd(bounds.getWidth());
        int hrect = rnd(bounds.getHeight());
        Box box = new Box(xrect, yrect, xrect+wrect, yrect+hrect);

        // Debug: draw rectangle around text.
        // g2d.drawRect(xrect, yrect, wrect, hrect);
        
        return box;
    }
    
    private static int rnd(double value)
    {
        return (int) Math.round(value);
    }

    public static class Box
    {
        private int tl[] = {0, 0}; public int[] getTL() { return tl; }
        private int br[] = {0, 0}; public int[] getBR() { return br; }
        private int tr[] = {0, 0}; public int[] getTR() { return tr; }
        private int bl[] = {0, 0}; public int[] getBL() { return bl; }
        
        public Box(int tlx, int tly, int brx, int bry)
        {
            tl[0] = tlx; tl[1] = tly;
            br[0] = brx; br[1] = bry;
            tr[0] = brx; tr[1] = tly;
            bl[0] = tlx; bl[1] = bry;
        }
    }

    public TestFontLayout2()
    {
        super();
        setPreferredSize(new Dimension(600,300));
    }

    @Override
    public void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g;
        
        // Ensure that the default painting occurs
        super.paintComponent(g);

        Font font = new Font("SansSerif", PLAIN, 21);
        FontRenderContext frc = g2d.getFontRenderContext();
        TextLayout layout1 = new TextLayout("This is a string", font, frc);
        TextLayout layout2 = new TextLayout("This is text", font, frc);

        g2d.setColor(RED);
        g2d.drawRect(getWidth()/2, getHeight()/2, 1,1);

        g2d.setColor(PINK);
        Box box = drawText(g2d, layout1, Anchor.UPPER_LEFT, 0, 0);

        g2d.setColor(BLUE);
        box = drawText(g2d, layout2, Anchor.UPPER_CENTER, getWidth()/2, 0);

        g2d.setColor(ORANGE);
        box = drawText(g2d, layout1, Anchor.UPPER_RIGHT, getWidth(), 0);

        g2d.setColor(DARK_GRAY);
        box = drawText(g2d, layout2, Anchor.MIDDLE_LEFT, 0, getHeight()/2);

        g2d.setColor(MAGENTA);
        box = drawText(g2d, layout1, Anchor.MIDDLE_CENTER, getWidth()/2, getHeight()/2);
        box = drawText(g2d, layout1, Anchor.UPPER_LEFT, box.getBL()[0], box.getBL()[1]);

        g2d.setColor(CYAN);
        box = drawText(g2d, layout2, Anchor.MIDDLE_RIGHT, getWidth(), getHeight()/2);

        g2d.setColor(YELLOW);
        box = drawText(g2d, layout1, Anchor.LOWER_LEFT, 0, getHeight());

        g2d.setColor(BLACK);
        box = drawText(g2d, layout2, Anchor.LOWER_CENTER, getWidth()/2, getHeight());

        g2d.setColor(ORANGE);
        box = drawText(g2d, layout1, Anchor.LOWER_RIGHT, getWidth(), getHeight());
    }

    public static void main(String[] args)
    {
        println("Draw text at specified anchor points...");
        JFrame frame = new JFrame("");
        frame.add(new TestFontLayout2());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

    }

    private static void println(Object obj)
    {
        System.out.println(obj.toString());
    }
}
// vi:set tabstop=4 hardtabs=4 shiftwidth=4 expandtab:
于 2021-06-03T21:10:18.847 回答