如何设置“备份”字体

时间:2018-09-28 09:27:32

标签: java swing fonts cjk

我正在使用Java 10,并进行摇摆。我使用的是DejaVu Sans Mono字体,因为我认为它看起来不错。但是,它对CJK字符的支持非常差,因此为了最大化支持,我想到了使用Noto Sans CJK作为备份。尽管我也可以将Noto Sans用于拉丁字符,但我不太喜欢它们的拉丁字符。

尽管这似乎是一个琐碎的问题,但我似乎找不到解决方法。即使您无法回答,我也感谢指针。

TL; DR:

我的问题

我无法使用DejaVu Sans Mono显示中文,日文或韩文字符

我的解决方案

使用Noto Sans CJK

我的解决方案出现的问题

诺托·桑斯(Noto Sans)的拉丁语很丑陋,并且不支持阿拉伯语

我的问题

我如何告诉JComponent,如果它无法在Font One(DejaVu)中找到字符,则应该改用Font 2(Noto)?

1 个答案:

答案 0 :(得分:1)

一种方法是在制作组件时检查字体显示相关字符的能力(并设置文本)。

这可以使用Font.canDisplayUpTo(String)之类的方法来实现。

E.G。

enter image description here

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);
    }
}