【问题标题】:How can we motivate Java & Swing to display all Glyphs / Characters from e.g. Comic Sans MS?我们如何激励 Java 和 Swing 显示所有字形/字符,例如Comic Sans MS?
【发布时间】:2021-12-25 02:41:35
【问题描述】:

在每个 Windows 应用程序中,都可以轻松使用和显示任何字体的任何字符。

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

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

显示“不寻常”字符非常有效 - 即使在这种网络公式中也是如此

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

旁注:

  • 我使用 IntelliJ
  • 源码文件使用utf8,完美显示测试字符串'አማርኛ'

代码示例:

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 完成它的工作?

【问题讨论】:

  • 你给出的代码示例中BoldFont是如何初始化的?
  • 那个字体不能显示那个字符 -> "አማርኛ".codePoints().mapToObj(ComicBld32::canDisplay).toList() (奇怪:如果我把那个文本复制到 Word 并将字体更改为 Comic Sana MS,它会更改为 Ebrima,不管我尝试什么) - 至少在我的系统上,该字体没有该代码点的字形:i.stack.imgur.com/zfB7C.png(在此处使用“Ebrima”)
  • 记事本很可能在骗你。 Comic Sans 不包含该角色。记事本正在使用其他字体来显示它。

标签: java swing utf-8 fonts


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多