【问题标题】:Custom font in JLabel is cut offJLabel 中的自定义字体被截断
【发布时间】:2025-12-02 05:10:01
【问题描述】:

我有一个已设置自定义字体“BP Diet”的 JLabel。如果我将它添加到 JFrame,文本看起来很好,但是一旦我将 JFrame 的布局更改为 FlowLayout,文本的顶部就会出现截断。当您将 JLabel 添加到 JPanel 并将其添加到 JFrame 时,也会出现同样的问题。我的字体在http://www.hichris.com/more/files/BPdiet.otf

下面是代码:

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);
    }
}

应该出现的样子

pack() 之后出现

大图指出 i & j 上方的点

感谢任何帮助!

【问题讨论】:

  • 我正在运行你的代码,没有任何东西被切断
  • 当你取消注释 setLayout 方法时,它会被切断:)
  • 好的,所以它不是切割,它只是从中间向上移动它。可以吗?我的意思是我的逻辑?
  • 不,这个东西实际上是被截断的,如果你放大你可以看到“i”的顶部被截断,但它只是在屏幕的顶部。如果您制作多个标签,您会看到它们都在顶部被切断。这就是奇怪的地方。我在想字体比普通字体大,这就是它被切断的原因。我还可以设置标签的最小尺寸,它仍然被切断。
  • 有人知道为什么会这样吗?

标签: java swing fonts jlabel flowlayout


【解决方案1】:

这是一个观察。 (代码在底部)

我得到了字体的字体规格,并在字体的重音和基线所在的位置画了一条线。您可以清楚地看到i 中的点位于重音线上方,也就是分界线。标签的首选大小是使用指标计算的。因此,基于此,首选大小将切断i 的一部分。 j 的底部不会被切断,因为考虑了下行线。

至于消息被切断的原因,可能有几个原因。在您的原始代码中,没有遇到问题,可能是因为字体太小,而 FlowLayout 有一个默认的 5px 间隙。在新示例中,它使用 pack() 切断,因为默认 BorderLayout 没有 没有默认间隙。

您可以解决此问题,就像 AndrewThompson 提到的那样,只需使用 EmptyBorder,或指定布局的间隙。要考虑的事情是FlowLayout 尊重组件的首选大小,因此标签将设置为其首选大小,同时考虑字体指标。 BorderLayout尊重首选尺寸,对于标签,将拉伸标签以适应布局位置并将文本垂直居中

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);
    }
}

【讨论】:

  • 是否可以根据字体大小计算出想要的空边框大小?
  • 问题是 FontMetrics is 应该计算出字体的大小。您的字体有些问题,导致它没有考虑到ij 的点。所以我认为没有办法,特别是对于这种字体
【解决方案2】:

我安装了字体并以这种方式使用Documentation中的setFont方法:

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);
    }
}

我删除了你的方法,设置字体更简单了,如果你还需要那个方法,那就回复一下,我可以尝试添加或者解决问题。

试试看,如果有帮助,告诉我:)

【讨论】:

  • 如何指定字体的位置?我仍然需要使用 createFont() 方法注册字体吗?只是不返回任何东西?
  • 字体在系统上的默认字体文件夹中查找,因此您无需执行任何操作,只需安装它。你试过这个程序吗?没有从哪里返回任何东西?
  • 字体不是系统的默认字体。我必须从我假设的文件中指定它吗?我也不想让用户安装它。
  • hmmph 然后让我尝试根据您的需要修复它:)
  • 另外,我将字体安装到我的系统上,字体的顶部仍然被切断。我使用了您给我的代码,但它没有按预期工作。 screencast.com/t/BOyVqMyEQ0Y