SWT中是否有办法简单地获得等宽字体,适用于各种操作系统?
例如。这适用于Linux,但不适用于Windows:
Font mono = new Font(parent.getDisplay(), "Mono", 10, SWT.NONE);
或者我是否需要尝试加载不同的字体(Consolas,Terminal,Monaco,Mono),直到一个不为空?或者,我可以在启动时在属性文件中指定它。
我尝试从Display获取系统字体,但这不是等宽字体。
答案 0 :(得分:37)
我花了一些时间来反对这个,直到我意识到显然eclipse必须能够访问monospace字体,以便在其文本字段,控制台等中使用。一点点挖掘出现了:
Font terminalFont = JFaceResources.getFont(JFaceResources.TEXT_FONT);
如果您感兴趣的是获取一些等宽字体,那么哪个有效。
编辑或根据@ ctron的评论:
Font font = JFaceResources.getTextFont();
编辑:警告(根据@ Lii的评论):这将为您提供已配置的文本字体,可由用户覆盖,也可能不是等宽字体。但是,它将与编辑器和控制台中使用的字体一致,可能是你想要的字体。
答案 1 :(得分:15)
根据Font Configuration Files相关API的JDK文档中关于Internationalization Support的部分,逻辑字体的概念用于定义某些与平台无关的字体,映射到默认字体配置文件中的物理字体:
Java平台定义了每个实现必须支持的五个逻辑字体名称:Serif,SansSerif,Monospaced,Dialog和DialogInput。这些逻辑字体名称以依赖于实现的方式映射到物理字体。
所以在你的情况下,我会尝试
Font mono = new Font(parent.getDisplay(), "Monospaced", 10, SWT.NONE);
获取运行代码的当前平台的物理等宽字体的句柄。
编辑:似乎SWT对逻辑字体一无所知(eclipse.org上的Bug 48055详细描述了这一点)。在这个错误报告中,建议使用hackish解决方法,其中可以从AWT字体中检索物理字体的名称......
答案 2 :(得分:4)
据我所知,AWT API不会暴露底层的Font信息。如果你能够实现它,我希望它是依赖于实现的。当然,比较一些JRE lib目录中的字体映射文件,我可以看到它们没有以一致的方式定义。
您可以加载自己的字体,但这似乎有点浪费,因为您知道平台附带了您需要的内容。
这是一个加载JRE字体的黑客:
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轻松重新配置用户界面。
答案 3 :(得分: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; }
答案 4 :(得分:1)
如果您只想使用Monospaced字体,请使用“Courier”=&gt; new Font(display, "Courier", 10, SWT.NORMAL)