【问题标题】:JTextArea and JTextPane font renderingJTextArea 和 JTextPane 字体渲染
【发布时间】:2013-10-27 19:05:13
【问题描述】:

似乎 JTextPane 和 JTextArea 以不同的方式呈现字体。它几乎不引人注意,但我仍然想知道它为什么会在那里。

我已经设置了一个 SSCCE,但你看不到它。最好的方法是使用 JTextArea 运行一个程序,然后将代码更改为 JTextPane 并再次运行它。它们应该以某种方式重叠,当您从一个窗口切换到另一个窗口时(使用 alt+ 选项卡),可以看到差异。您必须提供自己的 *.ttf 文件。

这是为什么呢?有没有办法强制 JTextPane 以与 JTextArea 相同的方式呈现文本?

SSCCE:

import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.IOException;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;


public class Main
{
public static void main(String[] args)
{
    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
    {
        if ("Nimbus".equals(info.getName()))
        {
            try
            {
                UIManager.setLookAndFeel(info.getClassName());
            }
            catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e)

            {
                System.out.println("No Nimbus!");
            }

            break;
        }
    }

    JFrame a = new JFrame("Test");
    a.setSize(600, 900);
    a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    a.getContentPane().setLayout(new BoxLayout(a.getContentPane(), BoxLayout.Y_AXIS));

    Font d = null;

    try
    {
        d = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("calibri_bold.ttf"));
        d = d.deriveFont(23f);
    }

    catch (FontFormatException | IOException e1)
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    final JTextPane b = new JTextPane();



    b.setBorder(new JTextArea().getBorder());
    b.setFont(d);

    b.addFocusListener(new FocusListener() {

        @Override
        public void focusGained(FocusEvent arg0) {
            b.repaint();
        }

        @Override
        public void focusLost(FocusEvent arg0) {
            b.repaint();
        }

    });
    b.setText("It seems that JTextPane and JTextArea are rendering fonts differently. It is barely noticeable, but I still want to know why is it there. I have set up a SSCCE, but you can't really see it. Best method would be to run a program with JTextArea, then change the code to JTextPane and run it again. They should overlap in a way when you change from one window to the other (with alt+ tab) the difference can be seen. Why is that? Is there a way to force the JTextPane to render the text the same way as JTextArea does?");
    a.getContentPane().add(b);

    final JTextArea c = new JTextArea();


    c.setFont(d);
    c.setText("It seems that JTextPane and JTextArea are rendering fonts differently. It is barely noticeable, but I still want to know why is it there. I have set up a SSCCE, but you can't really see it. Best method would be to run a program with JTextArea, then change the code to JTextPane and run it again. They should overlap in a way when you change from one window to the other (with alt+ tab) the difference can be seen. Why is that? Is there a way to force the JTextPane to render the text the same way as JTextArea does?");
    c.setLineWrap(true);
    c.setWrapStyleWord(true);
    a.getContentPane().add(c);

    a.setVisible(true);
}
}

【问题讨论】:

  • You will have to provide your own *.ttf file. - 当您使用默认字体时会发生什么?您的 .ttf 文件有问题吗?
  • 为什么会有问题?这是一个文件,它们都应该显示相同的...
  • 就在我的脑海中,有一些字体的渲染提示。 IE JTextPane 可能会使用带有浮点度量的 Graphics2D,而 JTextArea 可能不会。
  • Why would there be a problem with it? - 它应该为任何字体呈现相同的内容,那么为什么坚持我们使用自定义 .ttf 文件来使 SSCCE 复杂化呢?我一个人没有访问权限,所以我无法运行您的 SSCCE。提出问题的目的是在问题中仅包含相关信息。您还需要自己解决一些基本问题。

标签: java swing jtextarea jtextpane nimbus


【解决方案1】:
  • Nimbus L&F 有一些严重的问题,我们可以将这些问题称为Bugs

  • JTextArea 和另一个JComponents 冻结了Keys 中的一些UIManager

  • 您可以使用UIManager.getLookAndFeel().uninitialize(); 获取大多数密钥它们被冻结,但其中一些能够抵抗所有更改、黑客攻击、woodoo,但 FontJTextArea 不是这种情况

  • 请注意,您需要覆盖所有键 3 次,而不是像我的代码中演示的那样,请参阅注释 //...Defaults.put("TextPane.font", res);

  • UIManagermain class 的初始更改

  • UIManager.getLookAndFeel().uninitialize()之后;被称为

import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.FontUIResource;

public class Main {

    private JFrame frame = new JFrame("Test");
    private JTextPane textPane = new JTextPane();
    private JTextArea textArea = new JTextArea();
    private String str = "It seems that JTextPane and JTextArea are rendering fonts differently. "
            + "It is barely noticeable, but I still want to know why is it there. "
            + "I have set up a SSCCE, but you can't really see it. Best method would "
            + "be to run a program with JTextArea, then change the code to JTextPane "
            + "and run it again. They should overlap in a way when you change from one "
            + "window to the other (with alt+ tab) the difference can be seen. "
            + "Why is that? Is there a way to force the JTextPane to render the "
            + "text the same way as JTextArea does?";
    private javax.swing.Timer timer = null;
    final Font fnt = new Font("Brodway", Font.BOLD, 10);

    public Main() {
        textPane.setBorder(new JTextArea().getBorder());
        textPane.setText(str);
        textArea.setText(str);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new GridLayout(0, 1));
        frame.add(new JScrollPane(textPane));
        frame.add(new JScrollPane(textArea));
        frame.setVisible(true);
        frame.setSize(400, 400);
        start();
    }

    private void start() {
        timer = new javax.swing.Timer(2250, updateCol());
        timer.setRepeats(false);
        timer.start();
    }

    public Action updateCol() {
        return new AbstractAction("text load action") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {

                try {
                    LookAndFeel lnf = UIManager.getLookAndFeel().getClass().newInstance();
                    final FontUIResource res = new FontUIResource(fnt);
                    UIDefaults uiDefaults = lnf.getDefaults();
                    //uiDefaults.put("TextPane.font", res);
                    uiDefaults.put("TextArea.font", res);
                    UIManager.getLookAndFeel().uninitialize();
                    UIManager.setLookAndFeel(lnf);
                } catch (InstantiationException ex) {
                    Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
                } catch (UnsupportedLookAndFeelException ex) {
                    Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
                }
                UIDefaults defaults = UIManager.getDefaults();
                final FontUIResource res = new FontUIResource(fnt);
                //defaults.put("TextPane.font", res);
                defaults.put("TextArea.font", res);
                SwingUtilities.updateComponentTreeUI(frame);
            }
        };
    }

    public static void main(String[] args) {
        final FontUIResource res = new FontUIResource(new Font("Algerian", Font.BOLD, 10));
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                try {
                    UIManager.setLookAndFeel(info.getClassName());
                    UIDefaults defaults = UIManager.getDefaults();
                    defaults.put("TextPane.font", res);
                    defaults.put("TextArea.font", res);
                } catch (ClassNotFoundException | InstantiationException |
                        IllegalAccessException | UnsupportedLookAndFeelException e) {
                    System.out.println("No Nimbus!");
                }
                break;
            }
        }
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });
    }
}

【讨论】:

    猜你喜欢
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2013-04-29
    • 2021-02-06
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多