This blog is mainly about Java...

Tuesday, May 15, 2012

Add custom Font to your Java Swing application

This task was not that trivial as one might think.

It seems that you need to manually set the Font for each of the UI types.
To find out which one that was supported in my System, I did the following:


java.util.Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource) {
                System.out.println(key.toString());
            }
        }

Which printed out the following:


OptionPane.buttonFont
List.font
TableHeader.font
Panel.font
TextArea.font
ToggleButton.font
ComboBox.font
ScrollPane.font
Spinner.font
RadioButtonMenuItem.font
Slider.font
EditorPane.font
OptionPane.font
ToolBar.font
Tree.font
CheckBoxMenuItem.font
TitledBorder.font
FileChooser.listFont
Table.font
MenuBar.font
PopupMenu.font
Label.font
MenuItem.font
MenuItem.acceleratorFont
TextField.font
TextPane.font
CheckBox.font
ProgressBar.font
FormattedTextField.font
CheckBoxMenuItem.acceleratorFont
Menu.acceleratorFont
ColorChooser.font
Menu.font
PasswordField.font
InternalFrame.titleFont
OptionPane.messageFont
RadioButtonMenuItem.acceleratorFont
Viewport.font
TabbedPane.font
RadioButton.font
ToolTip.font
Button.font


Next, I had to set each one of these values manually:

 final Font TAHOMA_PLAIN_11 = new Font("Tahoma", Font.PLAIN, 11);
 final Font MONOSPACED_PLAIN_13 = new Font("Monospaced", Font.PLAIN, 13);
 final Font SEGOE_UI_PLAIN_12 = new Font("Segoe UI", Font.PLAIN, 12);
 final Font DIALOG_PLAIN_12 = new Font("Dialog", Font.PLAIN, 12);


        UIManager.put("OptionPane.buttonFont", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("List.font", TAHOMA_PLAIN_11);
        UIManager.put("TableHeader.font", TAHOMA_PLAIN_11);
        UIManager.put("Panel.font", TAHOMA_PLAIN_11);
        UIManager.put("TextArea.font", MONOSPACED_PLAIN_13);
        UIManager.put("ToggleButton.font", TAHOMA_PLAIN_11);
        UIManager.put("ComboBox.font", TAHOMA_PLAIN_11);
        UIManager.put("ScrollPane.font", TAHOMA_PLAIN_11);
        UIManager.put("Spinner.font", TAHOMA_PLAIN_11);
        UIManager.put("RadioButtonMenuItem.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("Slider.font", TAHOMA_PLAIN_11);
        UIManager.put("EditorPane.font", TAHOMA_PLAIN_11);
        UIManager.put("OptionPane.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("ToolBar.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("Tree.font", TAHOMA_PLAIN_11);
        UIManager.put("CheckBoxMenuItem.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("TitledBorder.font", TAHOMA_PLAIN_11);
        UIManager.put("FileChooser.listFont", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("Table.font", TAHOMA_PLAIN_11);
        UIManager.put("MenuBar.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("PopupMenu.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("Label.font", TAHOMA_PLAIN_11);
        UIManager.put("MenuItem.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("MenuItem.acceleratorFont", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("TextField.font", TAHOMA_PLAIN_11);
        UIManager.put("TextPane.font", TAHOMA_PLAIN_11);
        UIManager.put("CheckBox.font", TAHOMA_PLAIN_11);
        UIManager.put("ProgressBar.font", TAHOMA_PLAIN_11);
        UIManager.put("FormattedTextField.font", TAHOMA_PLAIN_11);
        UIManager.put("CheckBoxMenuItem.acceleratorFont", SwingUtils.DIALOG_PLAIN_12);
        UIManager.put("Menu.acceleratorFont", SwingUtils.DIALOG_PLAIN_12);
        UIManager.put("ColorChooser.font", SwingUtils.DIALOG_PLAIN_12);
        UIManager.put("Menu.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("PasswordField.font", TAHOMA_PLAIN_11);
        UIManager.put("InternalFrame.titleFont", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("OptionPane.messageFont", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("RadioButtonMenuItem.acceleratorFont", SwingUtils.DIALOG_PLAIN_12);
        UIManager.put("Viewport.font", TAHOMA_PLAIN_11);
        UIManager.put("TabbedPane.font", TAHOMA_PLAIN_11);
        UIManager.put("RadioButton.font", TAHOMA_PLAIN_11);
        UIManager.put("ToolTip.font", SwingUtils.SEGOE_UI_PLAIN_12);
        UIManager.put("Button.font", TAHOMA_PLAIN_11);

Running these different JUnit tests proved it worked:

@Test
    public void testFindJavaDefaultFonts() throws Exception {
        java.util.Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource) {
                Assert.assertEquals("Dialog", ((Font)value).getFamily());
            }
        }
    }
    
    @Test
    public void testFindSystemDefaultFonts() throws Exception {
        final Font font = new Font("Arial", Font.PLAIN, 12);
        UIManager.put("TextField.font", font);
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        UIManager.put("List.font", font);

        java.util.Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource) {
                Assert.assertFalse(key.toString().equals("TextField.font"));
                Assert.assertFalse(key.toString().equals("List.font"));
                
            }
        }
        
        Font font2 = UIManager.getFont("TextField.font");
        Assert.assertNotNull(font2);
        Assert.assertSame(font, font2);

        Font font3 = UIManager.getFont("List.font");
        Assert.assertNotNull(font3);
        Assert.assertSame(font, font3);
    }
    
    @Test
    public void testCustomFonts() throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtils.updateDefaultFonts(); //Where I put all my UIManager.put(...) lines
        java.util.Enumeration<Object> keys = UIManager.getDefaults().keys();
        while (keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource) {
                //This should fail if it comes here since we have set everything manually
                Assert.fail();
            }
        }
        
        Font font = UIManager.getFont("List.font");
        Assert.assertNotNull(font);
        Assert.assertEquals(font.getFamily(), "Tahoma");
    }

If there is an easier way to do this, please do share!

2 comments:

Unknown said...

I have used below method for setting the same font for all the UI components
public static void setUIFont(Font font, Container c)
{
for (Component component : container.getComponents())
{
component.setFont(font);
if ((component instanceof Container))
setUIFont(font, (Container)component);
}
}
Use it like this setUIFont(font, getContentPane());

Unknown said...

You may try this. Of course this sets the same font for all the UI components
public static void setUIFont(Font font, Container container)
{
for (Component component : container.getComponents())
{
component.setFont(font);
if ((component instanceof Container))
setUIFont(font, (Container)component);
}
}

Use it like this setUIFont(font, getContentPane());

Labels