java - 抗锯齿 JLabel

标签 java swing jlabel paintcomponent antialiasing

我试图创建一个自定义抗锯齿 JLabel,但我的文本仍然很僵硬。为什么这不起作用?

类似问题的答案包括更详细的解决方案,但我想知道为什么这不起作用。

编辑:

这是一个 SSCCE:

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

import javax.swing.JFrame;
import javax.swing.JLabel;

public class Tester {

    public static void main(String[] args) {
        SmoothLabel label = new SmoothLabel("Hello");
        label.setFont(new Font("Times New Roman", Font.PLAIN, 100));
        JFrame frame = new JFrame("SmoothLabel test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);

        frame.add(label);
        frame.setVisible(true);
    }
}

class SmoothLabel extends JLabel {

    String text;

    public SmoothLabel (String text) {
        super(text);

        this.text = text;
    }

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

        super.paintComponent(g2d);
    }
}

当我的字体大小为 100 时,我得到以下输出,它似乎没有消除锯齿:

100pt font

设置字体为150,突然出现反锯齿:

250pt font

最佳答案

截图

文本截图由:

  1. Graphics2D with RenderingHints.VALUE_TEXT_ANTIALIAS_ON(绿色边框)
  2. 一个标准的JLabel(蓝色边框)
  3. 一个SmoothLabel,强制执行RenderingHints.VALUE_TEXT_ANTIALIAS_ON(红色边框)

金属

光轮

CDE/主题

结论

SmoothLabel 支持/强制所有测试的 PLAF 中的抗锯齿文本。此处唯一尚未使用抗锯齿文本的 PLAF 是 CDE/Motif。

代码

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.LineBorder;

import java.io.*;
import javax.imageio.ImageIO;

class FontAntialiasingInSwingPLAFs {

    private JPanel gui = new JPanel(new BorderLayout(2, 2));
    String[] types = {"Graphics2D", "JLabel", "SmoothLabel"};
    private JLabel[] labels = {
        new JLabel(""), new JLabel(""), new SmoothLabel("")
    };
    private JLabel[] scaleLabels = {
        new JLabel(""), new JLabel(""), new JLabel("")
    };
    private Color[] colors = {Color.GREEN, Color.BLUE, Color.RED};
    private JComboBox<String> plaf = null;
    private UIManager.LookAndFeelInfo[] plafs;

    FontAntialiasingInSwingPLAFs() {
        initComponents();
    }

    private final void initComponents() {
        // here we design the layout and controls..
        JToolBar tb = new JToolBar("Controls");
        tb.setFloatable(false);
        gui.add(tb, BorderLayout.PAGE_START);

        Action save = new AbstractAction("Save") {

            @Override
            public void actionPerformed(ActionEvent e) {
                saveImages();
            }
        };
        tb.add(save);
        tb.addSeparator();

        plafs = UIManager.getInstalledLookAndFeels();
        plaf = new JComboBox<String>() {

            @Override
            public Dimension getMaximumSize() {
                return super.getPreferredSize();
            }
        };
        for (UIManager.LookAndFeelInfo info : plafs) {
            plaf.addItem(info.getName());
        }
        tb.add(plaf);
        ActionListener plafListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                changePLAF();
            }
        };
        plaf.addActionListener(plafListener);


        JPanel normalSize = new JPanel(new GridLayout(0, 3, 2, 2));
        gui.add(normalSize);
        for (int ii = 0; ii < labels.length; ii++) {
            labels[ii].setBorder(new LineBorder(colors[ii]));
            normalSize.add(labels[ii]);
        }

        JPanel scaledSize = new JPanel(new GridLayout(0, 3, 2, 2));
        gui.add(scaledSize, BorderLayout.PAGE_END);
        for (int ii = 0; ii < scaleLabels.length; ii++) {
            scaledSize.add(scaleLabels[ii]);
        }

        setText();
    }

    private void setText() {
        String plafName = (String) plaf.getSelectedItem();
        for (int ii = 1; ii < labels.length; ii++) {
            labels[ii].setText(plafName + " " + types[ii]);
        }
        labels[0].setIcon(new ImageIcon(getImage(plafName + " " + types[0])));
    }

    private void setScaledImages() {
        Dimension d = labels[0].getSize();
        for (int ii = 0; ii < labels.length; ii++) {
            BufferedImage scaledImage = getScaledImage(ii, 4, 200);
            scaleLabels[ii].setIcon(new ImageIcon(scaledImage));
        }
    }

    private BufferedImage getScaledImage(
            int index, int scale, int max) {
        BufferedImage input = getImage(index);
        int w = input.getWidth() * scale;
        int h = input.getHeight() * scale;
        w = w > max ? max : w;
        h = h > max ? max : h;
        BufferedImage temp = new BufferedImage(
                w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = temp.createGraphics();

        // do the drawing..
        g.scale(scale, scale);
        g.drawImage(input, 0, 0, gui);

        g.dispose();
        return temp;
    }

    private BufferedImage getImage(int index) {
        JLabel input = labels[index];
        int w = input.getWidth();
        int h = input.getHeight();
        BufferedImage temp = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = temp.createGraphics();

        // do the drawing..
        input.paintAll(g);

        g.dispose();
        return temp;
    }

    private BufferedImage getImage(String text) {
        int w = 5;
        int h = 5;
        BufferedImage temp = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = temp.createGraphics();

        FontRenderContext frc = g.getFontRenderContext();
        Font f = labels[1].getFont();
        GlyphVector gv = f.createGlyphVector(frc, text);
        Shape s1 = gv.getOutline();
        Shape s = gv.getOutline(-s1.getBounds().x, -s1.getBounds().y);
        Rectangle textBounds = s.getBounds();
        // recreate the image at the required size
        temp = new BufferedImage(
                textBounds.width,
                textBounds.height,
                BufferedImage.TYPE_INT_ARGB);
        // get the graphics object of the new image
        g = temp.createGraphics();
        g.setFont(f);
        // set a RenderingHints.KEY_TEXT_ANTIALIASING
        g.setRenderingHint(
                RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.setColor(Color.BLACK);

        // do the drawing..
        g.drawString(text, 0, textBounds.height);

        g.dispose();
        return temp;
    }

    private final void changePLAF() {
        int selected = plaf.getSelectedIndex();
        try {
            UIManager.setLookAndFeel(plafs[selected].getClassName());
            Container c = gui.getTopLevelAncestor();
            SwingUtilities.updateComponentTreeUI(c);
            setText();
            setScaledImages();
            if (c instanceof Window) {
                Window w = (Window) c;
                w.pack();
            } else {
                System.err.println(c.getClass().getSimpleName());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private final String getImageName(int index, boolean scaled) {
        String name = "";
        String sText = scaled ?  " Scaled" : "";
        if (index == 0) {
            name = (String)plaf.getSelectedItem() + " " + types[0];
        } else {
            String text = labels[index].getText();
            name = text;
        }
        String sPattern = "\\/";
        name = name.replaceAll(sPattern, "-");
        return name + sText + ".png";
    }

    private final void saveImages() {
        File f = new File(System.getProperty("user.home"));
        f = new File(f, "zundry");
        f = new File(f, "font-antialias");
        boolean success = true;
        if (!f.exists()) {
            success = f.mkdirs();
        }
        if (success) {
            // save the images!
            for (int ii = 0; ii < labels.length; ii++) {
                try {
                    File tempSmall = new File(f, getImageName(ii, false));
                    ImageIO.write(getImage(ii), "png", tempSmall);
                    File tempScaled = new File(f, getImageName(ii, true));
                    ImageIO.write(getScaledImage(ii, 4, 200), "png", tempScaled);
                    Desktop.getDesktop().open(f);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        } else {
            System.err.println(
                    "The directory could not be created!  "
                    + f.getAbsolutePath());
        }
    }

    public JComponent getGui() {
        return gui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                FontAntialiasingInSwingPLAFs fawp =
                        new FontAntialiasingInSwingPLAFs();

                JOptionPane.showMessageDialog(null, fawp.getGui());
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

class SmoothLabel extends JLabel {

    public SmoothLabel(String text) {
        super(text);
    }

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

        super.paintComponent(g2d);
    }
}

关于java - 抗锯齿 JLabel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21869693/

相关文章:

java - TextView 同时返回 true 和 false 语句,而不是仅返回 true

java - 消息监听器 onMessage() 方法不会从队列中读取消息

java - 在 JFrame 中格式化结果

java - 将文件打开到JLabel中

java - 如何用数字更新 JLabels

java - 使用循环从 JTextFields 获取值

java - 如何打开Jboss 4447端口?

java - 复选框不显示 ImageIcon

java - 组布局错误: can't find the wrong line in my code

java - 获取我的操作以查看我的其他对象