首页 > 解决方案 > 我们如何激励 Java 和 Swing 显示来自例如 Comic Sans MS 的所有字形/字符?

问题描述

在每个 Windows 应用程序中,使用和显示任何字体的任何字符都很容易。

例如:在记事本中显示“አማርኛ”并使用 Comic Sans MS:

  1. 打开记事本
  2. 更改字体: 格式 » 字体 » Comic Sans MS
  3. 粘贴文本:አማርኛ

显示“不寻常”字符非常有效——即使在这种网络公式中

在 Java 和 Swing 中,这是一场噩梦,这只是显示:▯▯▯▯

旁注:

代码示例:

Font ComicPln32 = new Font("Comic Sans MS", Font.PLAIN, 32);
Font ComicBld32 = new Font(ComicPln32.getName(), Font.BOLD, ComicPln32.getSize());

Border lineBorder = BorderFactory.createLineBorder(new Color(222, 49, 99), 2, true);
Border titleBorder = BorderFactory.createTitledBorder(lineBorder, "አማርኛ",
                     TitledBorder.LEFT, TitledBorder.TOP, BoldFont, Color.BLUE);
setBorder(titleBorder);

有没有简单的方法可以激励 Java 完成它的工作?

标签: javaswingutf-8fonts

解决方案


在 Java 中加载的显示字符的能力Font取决于字体本身。在其他软件(尤其是浏览器)中使用了很多技巧来“填充”不支持特定字形的字体,而另一种字体则支持。

但是针对这个具体问题。

[剧透警告:Comic Sans不支持这些角色。]

在此处输入图像描述
大多数(包括Comic Sans )都支持字符“abc” ,但不是该系统上的所有字体。

在此处输入图像描述
此系统上仅一种字体支持字符“አማርኛ”。

TestFonts

这是在该系统上产生上述输出的代码,使用Font.canDisplayUpTo(..). YMMV。

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;

public class TestFonts {

    JList<String> fontFamilyList;
    private JPanel gui;
    private String[] allFonts;

    TestFonts() {
        allFonts = GraphicsEnvironment.
                getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
    }

    private void updateList(String characters) {
        String s = characters;
        ListSelectionModel listSelectionModel = fontFamilyList.getSelectionModel();
        listSelectionModel.clearSelection();
        ListModel listModel = fontFamilyList.getModel();
        for (int ii = 0; ii < listModel.getSize(); ii++) {
            String fontFamily = listModel.getElementAt(ii).toString();
            Font font = new Font(fontFamily, Font.PLAIN, 10);
            if (font.canDisplayUpTo(s) < 0) {
                listSelectionModel.addSelectionInterval(ii, ii);
            }
        }
    }

    public static void main(String[] args) {

        Runnable r = () -> {
            final JFrame frame = new JFrame("Test Fonts");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            TestFonts tf = new TestFonts();

            frame.setContentPane(tf.getGUI());

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setLocationByPlatform(true);
            frame.setMinimumSize(frame.getSize());

            frame.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }

    public JPanel getGUI() {
        if (gui != null) return gui;
        gui = new JPanel(new BorderLayout(5, 5));
        gui.setBorder(new EmptyBorder(new Insets(4, 4, 4, 4)));
        //DefaultListModel allFontModel = new DefaultListModel(allFonts);
        fontFamilyList = new JList(allFonts);
        fontFamilyList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        fontFamilyList.setVisibleRowCount(40);
        gui.add(new JScrollPane(fontFamilyList), BorderLayout.LINE_START);

        final JTextField inputField = new JTextField(20);
        gui.add(inputField, BorderLayout.PAGE_START);
        DocumentListener documentListener = new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateList(inputField.getText());
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                updateList(inputField.getText());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                updateList(inputField.getText());
            }
        };
        inputField.getDocument().addDocumentListener(documentListener);
        return gui;
    }
}

推荐阅读