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 that when you change from one window to the other (with alt+ tab) the difference can be seen. You will have to provide your own *.ttf file.
Why is that? Is there a way to force the JTextPane to render the text the same way as JTextArea does?
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);
}
}
Nimbus L&F
has a few awfull issues, we can call those issues as a Bugs
JTextArea
and another JComponents
has frozen some of Keys
in UIManager
you can to UIManager.getLookAndFeel().uninitialize();
for most of Keys they are freeze, but some of them are able to resist against all changes, hacks, woodoo, but Font
for JTextArea
isn't this case
note you need to override all keys 3 times, not as is demonstratedin my code, see commented //...Defaults.put("TextPane.font", res);
initial changes in UIManager
from main class
UIManager.getLookAndFeel().uninitialize()
; is calledimport 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();
}
});
}
}