JTextArea和JTextPane字体呈现

时间:2013-10-18 20:01:50

标签: java swing jtextarea jtextpane nimbus

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

我已经设置了一个SSCCE,但你无法真正看到它。最好的方法是使用JTextArea运行程序,然后将代码更改为JTextPane并再次运行它。它们应该以一种方式重叠,当你从一个窗口更改为另一个窗口时(使用alt + tab),可以看到差异。您必须提供自己的* .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);
}
}

1 个答案:

答案 0 :(得分:4)

  • Nimbus L&F有一些问题,我们可以将这些问题称为Bugs

  • JTextArea而另一个JComponents冻结Keys

  • 中的部分UIManager
  • 对于他们冻结的大多数密钥,您可以UIManager.getLookAndFeel().uninitialize();,但其中一些可以抵御所有更改,黑客攻击,但Font JTextArea //...Defaults.put("TextPane.font", res);不是这种情况

  • 请注意,您需要覆盖所有密钥3次,而不是在我的代码中说明,请参阅评论UIManager

  • 来自main class

  • UIManager.getLookAndFeel().uninitialize()的初始更改

enter image description here

  • 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(); } }); } } 之后;被称为

enter image description here

{{1}}