Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Certain FontAwesome glyphs don't render in Java Swing JToolBar buttons

I'm having a problem displaying certain glyphs from the FontAwesome collection in buttons in a Swing JToolBar. Here is a screenshot to illustrate (notice that the top button in the toolbar on the right hand side is not a nice icon but instead shows three empty rectangles):

Screenshot to illustrate the problem

The code to reproduce this (at least on my Mac) is:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;![enter image description here][2]
import java.awt.FontFormatException;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToolBar;

public class TestFontAwesome {

    public static void main(String[] args) {
        new TestFontAwesome();
    }

    public TestFontAwesome() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try (InputStream is = TestFontAwesome.class.getResourceAsStream("/fontawesome-webfont_old.ttf")) {
                    Font font = Font.createFont(Font.TRUETYPE_FONT, is);
                    font = font.deriveFont(Font.PLAIN, 24f);

                    JToolBar toolBar = new JToolBar(JToolBar.VERTICAL);
                    JButton button1 = new JButton("\uf00e");
                    button1.setFont(font);
                    toolBar.add(button1);
                    JButton button2 = new JButton("\uf01e");
                    button2.setFont(font);
                    toolBar.add(button2);
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JButton("Irrelevant content..."));
                    frame.add(toolBar, BorderLayout.EAST);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException | FontFormatException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

}

I tried a few things: (1) Using different versions of the FontAwesome.ttf file, no change; (2) Trying different JDK versions, no change; (3) Displaying the same character in a regular JButton, this works as you can see in the following screenshot (so this is clearly not some issue with the font file):

Screenshot to show it works in a regular JButton

I tested on a non-Retina Mac and everything works, so I wonder if this is something specific to the Retina display. If anyone has any suggestions I'd appreciate hearing from you, thanks.

The code for the JButton only example (that works fine) is:

import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.JButton;
import javax.swing.JFrame;

public class TestFontAwesome2 {

    public static void main(String[] args) {
        new TestFontAwesome2();
    }

    public TestFontAwesome2() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try (InputStream is = TestFontAwesome.class.getResourceAsStream("/fontawesome-webfont_old.ttf")) {
                    Font font = Font.createFont(Font.TRUETYPE_FONT, is);
                    font = font.deriveFont(Font.PLAIN, 24f);

                    JButton button1 = new JButton("\uf00e");
                    button1.setFont(font);
                    JButton button2 = new JButton("\uf01e");
                    button2.setFont(font);
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new FlowLayout());
                    frame.add(new JButton("Irrelevant content..."));
                    frame.add(button1);
                    frame.add(button2);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException | FontFormatException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

}
like image 610
David Gilbert Avatar asked Aug 28 '14 11:08

David Gilbert


People also ask

Is it possible to use Font Awesome with Swing components?

If possible then how to use its icons with swing components (JButton or JLabel). I've used Font Awesome earlier with my Primefaces application. Show activity on this post. I would say "yes"... Copy the fontawesome-webfont.ttf file to your project (in the below example, I used it as an embedded resource)

What is the use of jtoolbar in JTable?

JToolBar provides a component which is useful for displaying commonly used actions or controls. This class implements accessibility support for the JToolBar class. A toolbar-specific separator. It creates a new tool bar; orientation defaults to HORIZONTAL. It creates a new tool bar with the specified orientation.

How do I use fontawesome web fonts in my project?

Copy the fontawesome-webfont.ttf file to your project (in the below example, I used it as an embedded resource) Using the Cheeatsheet, copy and past the icon you want to use into your code

What is the use of propertychangelistener in jtoolbar?

It appends a separator of default size to the end of the tool bar. It returns a properly configured PropertyChangeListener which updates the control as changes to the Action occur, or null if the default property change listener for the control is desired. Factory method which creates the JButton for Actions added to the JToolBar.


1 Answers

i think the problem is the ComponentUi
Means in special: ToolbarUi or ButtonUi (-Implementation).

ToolbarUi (and ButtonUi) are abstract classes, which are implemented in your selected LookAndFeel.
The Implementation can be totally different for each LookAndFeel.
Some Implementations do ignore some "user" settings like e.g Font or Color.

JButtons can use a different Ui-Implementation than Buttons which are added to JToolBars!
And this Implementation may ignore your Font settings.

See for example ButtonUi Implementation (only part of) in MetalLookAndFeel

public void update(Graphics g, JComponent c) {
   AbstractButton button = (AbstractButton)c;
   if ((c.getBackground() instanceof UIResource) &&
             button.isContentAreaFilled() && c.isEnabled()) {
       ButtonModel model = button.getModel();
       if (!MetalUtils.isToolBarButton(c)) {
           if (!model.isArmed() && !model.isPressed() &&
                   MetalUtils.drawGradient(
                   c, g, "Button.gradient", 0, 0, c.getWidth(),
                   c.getHeight(), true)) {
               paint(g, c);
               return;
           }
       }
...

Here you can see the different behaviour when MetalUtils.isToolbarButton

You have to check your LookAndFeel Implementation behaviour.
(Maybe there is also a different Implementation, depending the screen resolution)

like image 76
Ben Avatar answered Oct 30 '22 00:10

Ben