簡體   English   中英

Java - 幫助在任意錨點繪制文本的最佳庫

[英]Java - best library to help draw text at arbitrary anchor points

我熟悉如何使用各種 FontMetrics 函數將文本垂直、水平等居中。 但是,我正在尋找一個支持在相對於字符串的給定 xy 位置繪制文本的庫(例如,我希望字符串的中心位於 x、y,或者我希望它的右上角在這里,等等。 )

我發現JCommon及其文本錨點聲稱可以做到這一點,但我無法讓它正常工作, 而且論壇迄今為止沒有響應

我知道我可以自己編寫所有實用程序函數,但我想盡可能避免重新發明輪子。

我不知道有任何庫,但我猜如果你自己做,你只會使用 Graphics.translate() 將文本轉換為相對位置。

最后不得不自己做。 代碼如下:

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

您可能會查看TextLayout draw()getBounds()方法可以簡化編碼。

我發現TestFontLayout通過代碼I82Much是非常有用的,謝謝。 垂直對齊有一個小錯誤。 我的解決方法是使用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:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM