28

SWT 中有没有一种方法可以简单地获得等宽字体,并且可以在各种操作系统中使用?

例如。这适用于 Linux,但不适用于 Windows:


Font mono = new Font(parent.getDisplay(), "Mono", 10, SWT.NONE);

或者我是否需要一种方法来尝试加载不同的字体(Consolas、Terminal、Monaco、Mono)直到一个不为空?或者,我可以在启动时在属性文件中指定它。

我尝试从 Display 获取系统字体,但不是等宽字体。

4

5 回答 5

39

我花了一段时间猛烈抨击这个,直到我意识到显然 Eclipse 必须可以访问等宽字体才能在其文本字段、控制台等中使用。有点挖掘出现了:

Font terminalFont = JFaceResources.getFont(JFaceResources.TEXT_FONT);

如果您感兴趣的只是获取一些等宽字体,那么这很有效。

编辑:或基于@ctron 的评论:

Font font = JFaceResources.getTextFont();

编辑:警告(基于@Lii 的评论):这将为您提供配置的文本字体,它可以被用户覆盖,并且可能不是等宽字体。但是,它将与编辑器和控制台中使用的字体保持一致,这可能是您想要的。

于 2012-02-27T14:57:54.897 回答
16

根据国际化支持相关 API的 JDK 文档中的字体配置文件部分, Logical Font的概念用于定义某些与平台无关的字体​​,这些字体映射到默认字体配置文件中的物理字体:

Java 平台定义了每个实现必须支持的五个逻辑字体名称:Serif、SansSerif、Monospaced、Dialog 和 DialogInput。这些逻辑字体名称以与实现相关的方式映射到物理字体。

所以在你的情况下,我会尝试

Font mono = new Font(parent.getDisplay(), "Monospaced", 10, SWT.NONE);

获取运行代码的当前平台的物理等宽字体的句柄。

编辑:SWT 似乎对逻辑字体一无所知(eclipse.org 上的Bug 48055对此进行了详细描述)。在这个错误报告中,建议了一个骇人听闻的解决方法,其中物理字体的名称可以从 AWT 字体中检索...

于 2008-10-21T18:14:42.463 回答
4

据我所知,AWT API 不公开底层字体信息。如果你能得到它,我希望它依赖于实现。当然,比较几个 JRE lib 目录中的字体映射文件,我可以看到它们的定义方式不一致。

您可以加载自己的字体,但这似乎有点浪费,因为您知道该平台带有您需要的东西。

这是一个加载 JRE 字体的 hack:

private static Font loadMonospacedFont(Display display) {
    String jreHome = System.getProperty("java.home");
    File file = new File(jreHome, "/lib/fonts/LucidaTypewriterRegular.ttf");
    if (!file.exists()) {
        throw new IllegalStateException(file.toString());
    }
    if (!display.loadFont(file.toString())) {
        throw new IllegalStateException(file.toString());
    }
    final Font font = new Font(display, "Lucida Sans Typewriter", 10,
            SWT.NORMAL);
    display.addListener(SWT.Dispose, new Listener() {
        public void handleEvent(Event event) {
            font.dispose();
        }
    });
    return font;
}

它适用于 IBM/Win32/JRE1.4、Sun/Win32/JRE1.6、Sun/Linux/JRE1.6,但这是一种非常脆弱的方法。根据您对 I18N 的需求,那里也可能有问题(我还没有检查过)。

另一个技巧是测试平台上可用的字体:

public class Monotest {

    private static boolean isMonospace(GC gc) {
        final String wide = "wgh8";
        final String narrow = "1l;.";
        assert wide.length() == narrow.length();
        return gc.textExtent(wide).x == gc.textExtent(narrow).x;
    }

    private static void testFont(Display display, Font font) {
        Image image = new Image(display, 100, 100);
        try {
            GC gc = new GC(image);
            try {
                gc.setFont(font);
                System.out.println(isMonospace(gc) + "\t"
                        + font.getFontData()[0].getName());
            } finally {
                gc.dispose();
            }
        } finally {
            image.dispose();
        }
    }

    private static void walkFonts(Display display) {
        final boolean scalable = true;
        for (FontData fontData : display.getFontList(null, scalable)) {
            Font font = new Font(display, fontData);
            try {
                testFont(display, font);
            } finally {
                font.dispose();
            }
        }
    }

    public static void main(String[] args) {
        Display display = new Display();
        try {
            walkFonts(display);
        } finally {
            display.dispose();
        }
    }

}

这可能不是一个好方法,因为它可能会让您面临语言环境问题。此外,您不知道您遇到的第一个等宽字体是否不是一些绕组图标集。

最好的方法可能只是根据字体/区域设置映射白名单进行最佳猜测,并确保用户可以通过FontDialog轻松地重新配置 UI 以适合自己。

于 2008-10-22T15:50:58.713 回答
3

对于有同样问题的人,您可以下载任何字体 ttf 文件,将其放入资源文件夹(在我的情况下为 /font/ * *.ttf)并将此方法添加到您的应用程序中。这是100%的工作。

public Font loadDigitalFont(int policeSize) {
    URL fontFile = YouClassName.class
            .getResource("/fonts/DS-DIGI.TTF");
    boolean isLoaded = Display.getCurrent().loadFont(fontFile.getPath());
    if (isLoaded) {
        FontData[] fd = Display.getCurrent().getFontList(null, true);
        FontData fontdata = null;
        for (int i = 0; i < fd.length; i++) {
            if (fd[i].getName().equals("DS-Digital")) {
                fontdata = fd[i];
                break;
            }}
        if (fontdata != null) {
            fontdata.setHeight(policeSize);
            fontdata.setStyle(SWT.BOLD);return new Font(getDisplay(), fontdata));}
    }return null;   }
于 2013-03-07T11:23:05.853 回答
1

如果您只想要等宽字体,请使用“Courier”=>new Font(display, "Courier", 10, SWT.NORMAL)

于 2008-12-11T11:38:28.327 回答