如何在Java2D中使旋转文本看起来好看

4
我的问题不是关于如何使用Java2D旋转文本;我知道如何做到这一点。我不知道的是如何使旋转后的文本“看起来好看”。例如,如果您在PowerPoint中创建一个文本框并将其旋转,无论旋转角度如何,文本都会清晰明了。然而,使用g2D.drawString()绘制的文本在0度或90度时还可以,但在其他角度时就不太好看了。有没有一种方法可以操纵文本以清理或锐化它?如果有的话,如果有人能指点我去哪里学习如何做到这一点,我将非常感激。
下面是一个小程序,说明了我所说的内容。更大的字体旋转时还好,但仍然不太专业。旋转后的较小字体非常糟糕。
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class RotateTest extends JPanel {
    String message = "How does this text look?";

    public RotateTest() {
        this.setPreferredSize(new Dimension(640, 280));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2D = (Graphics2D) g;

        g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                       RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        g2D.setFont(new Font("MyriadPro", Font.BOLD, 20));
        g2D.drawString(message, 80, 20);

        AffineTransform orig = g2D.getTransform();

        double angle = Math.toRadians(7.0);
        g2D.rotate(-angle, -10, 80);
        g2D.drawString(message, 80, 80);
        g2D.setTransform(orig);

        angle = Math.toRadians(30.0);
        g2D.rotate(-angle, -40, 80);
        g2D.drawString(message, 60, 260);
        g2D.setTransform(orig);

        g2D.setFont(new Font("MyriadPro", Font.BOLD, 12));
        g2D.drawString(message, 380, 20);

        angle = Math.toRadians(7.0);
        g2D.rotate(-angle, -10, 80);
        g2D.drawString(message, 380, 120);
        g2D.setTransform(orig);

        angle = Math.toRadians(30.0);
        g2D.rotate(-angle, -40, 80);
        g2D.drawString(message, 320, 400);
        g2D.setTransform(orig);
    }

    private void display() {
        JFrame f = new JFrame("RotateTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new RotateTest().display();
            }
        });
    }
}

你有任何代码可以展示吗? - mprabhat
2个回答

7

我曾经遇到过类似的问题,通过将文本以高精度绘制成图像,然后旋转图像来解决它。

以下是代码:

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class RotatedText extends JPanel {
    String message = "How does this text look?";

    public RotatedText() {
        this.setPreferredSize(new Dimension(640, 280));
    }

    public BufferedImage createStringImage(Graphics g, String s) {
        int w = g.getFontMetrics().stringWidth(s) + 5;
        int h = g.getFontMetrics().getHeight();

        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D imageGraphics = image.createGraphics();
        imageGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        imageGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        imageGraphics.setColor(Color.BLACK);
        imageGraphics.setFont(g.getFont());
        imageGraphics.drawString(s, 0, h - g.getFontMetrics().getDescent());
        imageGraphics.dispose();

        return image;
    }

    private void drawString(Graphics g, String s, int tx, int ty, double theta, double rotx, double roty) {
        AffineTransform aff = AffineTransform.getRotateInstance(theta, rotx, roty);
        aff.translate(tx, ty);

        Graphics2D g2D = ((Graphics2D) g);
        g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g2D.drawImage(createStringImage(g, s), aff, this);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setFont(new Font("MyriadPro", Font.BOLD, 20));

        drawString(g, message, 80, 20, 0, 0, 0);
        drawString(g, message, 80, 80, -Math.toRadians(7.0), -10, 80);
        drawString(g, message, 60, 260, -Math.toRadians(30.0), -40, 80);

        g.setFont(new Font("MyriadPro", Font.BOLD, 12));

        drawString(g, message, 380, 20, 0, 0, 0);
        drawString(g, message, 380, 120, -Math.toRadians(7.0), -10, 80);
        drawString(g, message, 320, 400, -Math.toRadians(30.0), -40, 80);
    }

    private void display() {
        JFrame f = new JFrame("RotateTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new RotatedText().display();
            }
        });
    }
}

1
我没有时间测试这个,但是以下代码会有帮助吗?
Graphics2D g2d; 
g2d.setRenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

这只适用于Graphics2D。如果您正在使用普通的Graphics,则可以将您的Graphics对象转换为2D版本,如下所示:

Graphics2D g2d = (Graphics2D) g; //if Graphics object name is g.

告诉我吧!祝你好运


谢谢Byron...我试过了,但旋转后的文本仍然不太好看(请参见上面的示例代码)。 - Bill Doss
我试了一下你的代码,看到你遇到的问题了。说实话,我不确定为什么文本看起来那么糟糕,但我的直觉告诉我这可能与字体无法应对旋转有关。 - Byron Voorbach
如果您查看此网站:http://www.subbu.org/javaapps/rotate/RotateTextDemo.html,您的代码在此示例中是否也很丑?(不是我的代码+它不是Graphics2D) - Byron Voorbach
嗨,拜伦,谢谢你的回复。抱歉我没有回答;我一直在外面并且过去几周一直在做其他事情。我想我会尝试使用不同的字体,并查看在不同角度下是否有更好的效果。 - Bill Doss
我完全忘记了这个问题,直到今天偶然发现我有一个回复——就是上面那个。我一直在使用投石机MS字体,看起来还不错。 sina72上面的方法非常有效。 - Bill Doss
我已经测试了应用RenderingHints,这是sina72用来配置我的Graphics2D的,即使没有创建图像,它也运行良好。虽然在更改旋转时有些字母会跳动,因为它不是作为图像呈现的,但它的工作非常出色 :) - Martin Krajčírovič

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接