不支持字符的默认内置字体的系统字体
System Font with default built-in fonts for unsupported characters
我在 Windows 上为 JLabel
使用 Segoe UI
系统字体。 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);
使用 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
class 是必需的,因为需要另一个 Font
的 Font
的构造函数受到保护。
public static Font createFont(final String family, final int style, final int size) {
return new NonUIResourceFont(StyleContext.getDefaultStyleContext().getFont(family, style, size));
}
public static class NonUIResourceFont extends Font {
public NonUIResourceFont(final Font font) {
super(font);
}
}
我在 Windows 上为 JLabel
使用 Segoe UI
系统字体。 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);
使用 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
class 是必需的,因为需要另一个 Font
的 Font
的构造函数受到保护。
public static Font createFont(final String family, final int style, final int size) {
return new NonUIResourceFont(StyleContext.getDefaultStyleContext().getFont(family, style, size));
}
public static class NonUIResourceFont extends Font {
public NonUIResourceFont(final Font font) {
super(font);
}
}