如何设置 "backup" 字体
How to set a "backup" font
我正在使用 Java 10,挥杆。我使用的是 DejaVu Sans Mono 字体,因为我觉得它看起来不错。但是,它对 CJK 字符的支持很差,所以为了最大限度地支持,我想到了使用 Noto Sans CJK 作为备份。虽然我也可以用 Noto Sans 来写拉丁字符,但我不太喜欢他们的拉丁字符。
尽管这似乎是一个微不足道的问题,但我似乎无法找到解决方法。就算答不上来,也请指点。
长话短说:
我的问题
我无法使用 DejaVu Sans Mono 显示中文、日文或韩文字符
我的解决方案
使用 Noto Sans CJK
我的解决方案存在问题
Noto Sans 不支持拉丁语,不支持阿拉伯语
我的问题
我如何告诉 JComponent 如果它在字体一 (DejaVu) 中找不到字符,它应该改用字体二 (Noto)?
一种方法是在制作组件(和设置文本)时检查字体是否能够显示相关字符。
这可以使用 Font.canDisplayUpTo(String)
.
等方法来实现
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.*;
public class FallbackFont {
private JComponent ui = null;
private final String[] fontFamilies = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
String[] examplesTexts = {
"The quick brown fox jumps over the lazy dog.", // English
"\u6253\u5370\u8FC7\u671F\u8BC1\u4E66\u8BB0\u5F55", // Chinese
"\u0627\u0644\u0633\u0644\u0627\u0645 "
+ "\u0639\u0644\u064A\u0643\u0645", // Arabic
new String(Character.toChars(128176))
};
String[] preferredFonts = {
"DejaVu Sans Mono",
"Microsoft JhengHei",
"Noto Sans CJK TC Black", // has strange display problem here ..
};
FallbackFont() {
initUI();
}
private HashMap getCompatibleFonts(String text) {
HashMap cF = new HashMap<>();
for (String font : fontFamilies) {
Font f = new Font(font, Font.PLAIN, 1);
if (f.canDisplayUpTo(text) < 0) {
cF.put(font, f);
}
}
return cF;
}
private Font getPreferredFontForText(String text) {
HashMap compatibleFonts = getCompatibleFonts(text);
for (String preferredFont : preferredFonts) {
Font font = (Font) compatibleFonts.get(preferredFont);
if (font != null) {
return font;
}
}
Set keySet = compatibleFonts.keySet();
String firstCompatibleFont = (String) keySet.iterator().next();
return (Font) compatibleFonts.get(firstCompatibleFont);
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new GridLayout(0, 2, 4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
for (String text : examplesTexts) {
Font font = getPreferredFontForText(text);
JButton b = new JButton(text);
b.setFont(font.deriveFont(b.getFont().getSize2D()));
ui.add(b);
ui.add(new JLabel(font.getName()));
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
FallbackFont o = new FallbackFont();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
我正在使用 Java 10,挥杆。我使用的是 DejaVu Sans Mono 字体,因为我觉得它看起来不错。但是,它对 CJK 字符的支持很差,所以为了最大限度地支持,我想到了使用 Noto Sans CJK 作为备份。虽然我也可以用 Noto Sans 来写拉丁字符,但我不太喜欢他们的拉丁字符。
尽管这似乎是一个微不足道的问题,但我似乎无法找到解决方法。就算答不上来,也请指点。
长话短说:
我的问题
我无法使用 DejaVu Sans Mono 显示中文、日文或韩文字符
我的解决方案
使用 Noto Sans CJK
我的解决方案存在问题
Noto Sans 不支持拉丁语,不支持阿拉伯语
我的问题
我如何告诉 JComponent 如果它在字体一 (DejaVu) 中找不到字符,它应该改用字体二 (Noto)?
一种方法是在制作组件(和设置文本)时检查字体是否能够显示相关字符。
这可以使用 Font.canDisplayUpTo(String)
.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.*;
public class FallbackFont {
private JComponent ui = null;
private final String[] fontFamilies = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
String[] examplesTexts = {
"The quick brown fox jumps over the lazy dog.", // English
"\u6253\u5370\u8FC7\u671F\u8BC1\u4E66\u8BB0\u5F55", // Chinese
"\u0627\u0644\u0633\u0644\u0627\u0645 "
+ "\u0639\u0644\u064A\u0643\u0645", // Arabic
new String(Character.toChars(128176))
};
String[] preferredFonts = {
"DejaVu Sans Mono",
"Microsoft JhengHei",
"Noto Sans CJK TC Black", // has strange display problem here ..
};
FallbackFont() {
initUI();
}
private HashMap getCompatibleFonts(String text) {
HashMap cF = new HashMap<>();
for (String font : fontFamilies) {
Font f = new Font(font, Font.PLAIN, 1);
if (f.canDisplayUpTo(text) < 0) {
cF.put(font, f);
}
}
return cF;
}
private Font getPreferredFontForText(String text) {
HashMap compatibleFonts = getCompatibleFonts(text);
for (String preferredFont : preferredFonts) {
Font font = (Font) compatibleFonts.get(preferredFont);
if (font != null) {
return font;
}
}
Set keySet = compatibleFonts.keySet();
String firstCompatibleFont = (String) keySet.iterator().next();
return (Font) compatibleFonts.get(firstCompatibleFont);
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new GridLayout(0, 2, 4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
for (String text : examplesTexts) {
Font font = getPreferredFontForText(text);
JButton b = new JButton(text);
b.setFont(font.deriveFont(b.getFont().getSize2D()));
ui.add(b);
ui.add(new JLabel(font.getName()));
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
FallbackFont o = new FallbackFont();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}