码:

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;

public class TextRectangle extends JFrame {

    private static final long serialVersionUID = 1L;

    public static void main(String[] a) {
        TextRectangle f = new TextRectangle();
        f.setSize(300, 300);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(
            RenderingHints.KEY_RENDERING,
            RenderingHints.VALUE_RENDER_QUALITY);

        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, getWidth(), getHeight());

        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Calibri", Font.BOLD, 18));
        g2d.drawString("Why does this text look so ugly?", 30, 150);
    }

}

结果:

如您所见,字母间距不均匀。有时是1像素,有时是2甚至3像素。另一个问题是“i”上方的点宽于底部。

用文本编辑器编写的相同文本看起来要好得多。您知道如何解决此问题吗?

我的环境是Windows 8.1,Java 1.8。

最佳答案

默认情况下,图形上下文使用整数指标-意味着将四舍五入应用于字形形状的位置 vector 。

您可以使用以下命令切换到分数指标:

g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
    RenderingHints.VALUE_FRACTIONALMETRICS_ON);

如您所见,没有使用亚像素抗锯齿(仅使用灰色抗锯齿像素)。您可以启用亚像素抗锯齿以便在LCD屏幕上更清晰易读:
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);

有4种模式:
  • VALUE_TEXT_ANTIALIAS_LCD_HRGB:水平方向的RGB
  • VALUE_TEXT_ANTIALIAS_LCD_HBGR:水平BGR
  • VALUE_TEXT_ANTIALIAS_LCD_VRGB:垂直方向的RGB
  • VALUE_TEXT_ANTIALIAS_LCD_VBGR:垂直BGR

  • 我还没有找到在哪里查询当前显示和方向的适当值。某些显示可能会倾斜(横向/纵向)甚至旋转,需要在绘画时重新检测该模式。

    编辑

    我在Filthy Rich Clients书中找到了一些东西:显然,Java AWT Toolkit可以提供适当的呈现提示:
    Map<?, ?> desktopHints =
        (Map<?, ?>) Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints");
    
    Graphics2D g2d = (Graphics2D) g;
    if (desktopHints != null) {
        g2d.setRenderingHints(desktopHints);
    }
    // no need to set more rendering hints
    

    在我的系统上,这与上面的代码相同,使用分数度量和LCD HRGB抗锯齿效果呈现文本。我的系统上的提示是:
  • 特定于文本的抗锯齿启用键: LCD HRGB抗锯齿文本模式
  • 特定于文本的LCD对比度键: 120
  • 10-07 19:21
    查看更多