2

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!

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • I'm running your code and nothing gets cut off – Paul Samsotha May 23 '14 at 18:33
  • When you un-comment the setLayout method it get's cut off :) – Chris Smith May 23 '14 at 19:45
  • ok so it isn't cutting, it's just moving it up from the middle. Is it ok? I mean my logic? – Frakcool May 23 '14 at 22:07
  • No, the thing is actually cut off, if you zoom in you can see that the top of the "i" is cut off but it is just at the top of the screen. If you make multiple Labels you can see that they all get cut off at the top. That is what's weird. I'm thinking that the font is bigger than a regular font and that is why it is cut off. I can also set the minimum size of the label and it is still cut off. – Christopher Smith May 23 '14 at 23:45
  • Does anybody know why this could be? – Christopher Smith May 24 '14 at 18:22
  • @peeskillet I see the problem on Windows 7. Try the edited source. It vaguely reminds me of a problem where the font did not return correct size information.. – Andrew Thompson May 25 '14 at 06:19
  • BTW - one hack/work-around is `label.setBorder(new EmptyBorder(8, 0, 0, 0));`.. – Andrew Thompson May 25 '14 at 06:25
  • @AndrewThompson the font does return the correct size, _kinda_. It's the `i` that's the black sheep of the font family. It doesn't want to adhere to the accent restrictions :-) – Paul Samsotha May 25 '14 at 07:05
  • A solution could be to create a class with an array of fonts and their corresponding border. – Christopher Smith May 28 '14 at 14:14

2 Answers2

5

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);
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Is it possible to calculate the desired empty border size based on the size of the font? – Christopher Smith May 25 '14 at 16:16
  • 1
    The thing is the FontMetrics _is_ supposed to figure out the size of the font. Something is screwy with your font, causing it not to take into account the points of the `i` and `j`. So I don't think there is a way, for this font in particular – Paul Samsotha May 25 '14 at 16:21
1

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 :)

Frakcool
  • 10,915
  • 9
  • 50
  • 89