java - Custom font in JLabel is cut off

I have a JLabel that I have set the custom font, "BP Diet" to it. If I add this to a JFrame, the text appears fine, but as soon as I change the layout of the JFrame to FlowLayout, the top of the text appears cut off. This same problem occurs when you add the JLabel to a JPanel and add that to the JFrame. I have the font available at http://www.hichris.com/more/files/BPdiet.otf

Here is the code below:

import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.net.URL;

public class FontSizeTest {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel(
                "AaBbCcDdEeFfGgHhIiJjKk");
        label.setFont(createFont());
        frame.add(label);
        frame.pack();
        frame.setMinimumSize(frame.getMinimumSize());
        frame.setVisible(true);
    }

    static Font createFont() {
        Font customFont = null;
        try {
            URL url = new URL("http://www.hichris.com/more/files/BPdiet.otf");
            InputStream is = url.openStream();
            customFont = Font.createFont(Font.TRUETYPE_FONT, is);
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            ge.registerFont(customFont);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return customFont.deriveFont(25f);
    }
}

As it should appear

Showing full font

As it appears after pack()

As it first appears

Bigger view pointing out the dots above i & j

As it first appears

Any help is appreciated!

2 Answers

  1. Larry- Reply

    2019-11-13

    Here's an observation. (code at bottom)

    enter image description here

    I got the font metrics of the font and drew a line where the accent and base line of the font are. You can clearly see that the dot in the i goes above the above the accent line, which is the cutoff. The preferred size of the label is calculated using the metrics. So based of the this, the preferred size will cut off part of the i. The bottom of the j will not get cut off though, as the descender line is taken into account.

    As for why the message gets cut off, there could be a few reason. In your original code, the problem wasn't encountered, possibly because the font was too small, and the FlowLayout has a default 5px gap. In the new example it cut off, using pack() because the default BorderLayout has no default gap.

    You can fix this, like AndrewThompson mentioned, by just using an EmptyBorder, or specify the gap for the layout. Things to consider are that FlowLayout respects preferred size of components, so the label will get set to its preferred size, taking the font metrics into consideration. The BorderLayout will not respect preferred sizes, and for the label, will stretch the label to fit the layout position and center the text vertically

    import java.awt.*;
    import javax.swing.*;
    import java.io.*;
    import java.net.URL;
    
    public class FontSizeTest {
        static String message = "AaBbHhIiJjKk";
    
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(createFontTestPanel());
            frame.pack();
            frame.setMinimumSize(frame.getMinimumSize());
            frame.setVisible(true);
        }
    
        static Font font = createFont();
    
        static JPanel createFontTestPanel() {
            return new JPanel() {
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    g.setFont(font);
                    FontMetrics fm = g.getFontMetrics();
                    int stringHeight = fm.getAscent();
                    int stringWidth = fm.stringWidth(message);
    
                    int beginString = getWidth()/2 - stringWidth/2;
                    int baseString = getHeight()/2 + stringHeight/2;
    
                    // draw accent line
                    g.drawLine(0, baseString - stringHeight, getWidth(), baseString - stringHeight);
                    // draw base line
                    g.drawLine(0, baseString, getWidth(), baseString);
                    // draw message
                    g.drawString(message, beginString, baseString);
                }
    
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(500, 150);
                }
            };
        }
    
        static Font createFont() {
            Font customFont = null;
            try {
                URL url = new URL("http://www.hichris.com/more/files/BPdiet.otf");
                InputStream is = url.openStream();
                customFont = Font.createFont(Font.TRUETYPE_FONT, is);
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                ge.registerFont(customFont);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return customFont.deriveFont(50f);
        }
    }
    
  2. Laurent- Reply

    2019-11-13

    I installed the font and used setFont method from Documentation this way:

    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.FontFormatException;
    import java.awt.GraphicsEnvironment;
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    
    public class Test {
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setLayout(new FlowLayout());//Un-commenting causes text to be cut off
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JLabel label = new JLabel(
                    "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz");
            label.setFont(new Font("BPDiet", Font.BOLD, 15));
            frame.add(label);
            frame.setSize(800, 500);
            frame.setVisible(true);
        }
    }
    

    I deleted your method and setted font in an easier way, if you still need that method, then just reply so I can try adding or solving the issue.

    Try it and tell me if it helps :)

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>