我在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);
发布于 2020-11-04 01:23:05
最简单的解决方案是使用StyleContext#getFont
,它将调用内部接口FontUtilities#getCompositeFontUIResource(Font)
。此函数将创建一个复合字体,该字体将对不支持的字符使用备用字体。
请注意,您无法控制将使用哪种字体作为备用字体。
因为返回的字体是一个UIResource
,所以我们需要包装它,以避免被LookAndFeel覆盖。自定义NonUIResourceFont
类是必需的,因为接受另一个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);
}
}
发布于 2020-11-02 03:21:06
使用this answer中建议的想法,您可以使用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
中按需显示。
https://stackoverflow.com/questions/64618774
复制相似问题