问题描述
我在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);
解决方法
使用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