Java - 帮助在任意锚点绘制文本的最佳库

时间:2010-02-17 05:11:45

标签: java swing text graphics2d

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

我发现JCommon及其文本主页意图执行此操作,但我无法将其工作并the forum is heretofore unresponsive

我知道我可以自己编写所有实用程序功能但是我想尽可能避免重新发明轮子。

4 个答案:

答案 0 :(得分:1)

我不知道有任何库,但我猜你自己就可以使用Graphics.translate()将文本翻译成相对位置。

答案 1 :(得分: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);

    }
}

alt text http://grab.by/2WlM

答案 2 :(得分:0)

您可以查看TextLayoutdraw()getBounds()方法可以简化编码。

答案 3 :(得分:0)

我发现 I82MuchTestFontLayout 代码非常有用,谢谢。垂直对齐有一个小错误。我的解决方法是使用 bounds.getY() 而不是 bounds.getHeight() 进行“偏移”计算。此外,drawText(...) 方法已修改为返回自定义 Box 类以提供绘制文本的角坐标,以便下一次绘制可以使用 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: