系统字体,带有默认内置字体,用于不支持的字符

问题描述

我在Windows上将Segoe UI使用JLabel系统字体。 Segoe UI不支持CJK字符,但是它不会显示认字符(例如Font.DIALOG),而是显示占位符。

我想在Windows上使用Segoe UI,因为它看起来更适合拉丁字符,但是我不想失去对完全显示CJK字符的支持

有没有一种组合字体的方法?首选使用Segoe UI作为拉丁字符,但认为Font.DIALOG(或任何其他系统认值),以便至少呈现可读字符。

例如

Font font = new Font("Segoe UI",Font.PLAIN,12);
label.setFont(font);

CJK characters are not rendered

解决方法

使用this答案中提出的想法,您可以使用JLabel显示HTML的功能来在需要时切换字体:

public static String transformText(String text) {
    Font defaultFont = new JLabel().getFont();
    Font segoe = new Font("Segoe UI",defaultFont.getStyle(),defaultFont.getSize());
    StringBuilder sb = new StringBuilder(
        "<html><span style=\"font-family: " + defaultFont.getFamily() + "\">");
    boolean inDefaultFont = true;

    for (int i = 0; i < text.length(); i++) {
        char current = text.charAt(i);
        if (segoe.canDisplay(current) ^ inDefaultFont) {
            // font already correct
            sb.append(current);
        } else {
            // switch font
            sb.append("</span><span style=\"font-family: "
                + (inDefaultFont ? segoe.getFamily() : defaultFont.getFamily())
                + "\">" + current);
            inDefaultFont = !inDefaultFont;
        }
    }
    sb.append("</span></html>");

    System.out.println(sb.toString());
    return sb.toString();
}

从测试输入日本 한국 01 abc到输出<html><span style="font-family: Dialog">日本</span><span style="font-family: Segoe UI"> </span><span style="font-family: Dialog">한국</span><span style="font-family: Segoe UI"> 01 abc</span></html>的结果,该结果按需要显示在JLabel中。

,

最简单的解决方案是使用StyleContext#getFont,它将调用内部api FontUtilities#getCompositeFontUIResource(Font)。此功能将创建一个复合字体,该字体将对不支持的字符使用后备字体。

请注意,您无法控制将哪种字体用作后备广告。

因为返回的字体是UIResource,所以我们需要将其包装起来,以免被LookAndFeel覆盖。自定义NonUIResourceFont类是必需的,因为采用另一个Font的{​​{1}}的构造函数受到保护。

Font