java SWT - 获取等宽字体的操作系统不可知方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/221568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SWT - OS agnostic way to get monospaced font
提问by JeeBee
Is there a way in SWT to get a monospaced font simply, that works across various operating systems?
SWT 中是否有一种方法可以简单地获得等宽字体,可以在各种操作系统上使用?
For example. this works on Linux, but not Windows:
例如。这适用于 Linux,但不适用于 Windows:
Font mono = new Font(parent.getDisplay(), "Mono", 10, SWT.NONE);
or do I need to have a method that tries loading varying fonts (Consolas, Terminal, Monaco, Mono) until one isn't null? Alternatively I could specify it in a properties file on startup.
或者我是否需要一种方法来尝试加载不同的字体(Consolas、Terminal、Monaco、Mono)直到一个不为空?或者,我可以在启动时在属性文件中指定它。
I tried getting the system font from Display, but that wasn't monospaced.
我尝试从 Display 获取系统字体,但这不是等宽的。
采纳答案by fhe
According to the section on Font Configuration Filesin the JDK documentation of Internationalization Support-related APIs, the concept of Logical Fonts is used to define certain platform-independent fonts which are mapped to physical fonts in the default font configuration files:
根据国际化支持相关 API的 JDK 文档中的字体配置文件部分,逻辑字体的概念用于定义某些与平台无关的字体,这些字体映射到默认字体配置文件中的物理字体:
The Java Platform defines five logical font names that every implementation must support: Serif, SansSerif, Monospaced, Dialog, and DialogInput. These logical font names are mapped to physical fonts in implementation dependent ways.
Java 平台定义了每个实现都必须支持的五个逻辑字体名称:Serif、SansSerif、Monospaced、Dialog 和 DialogInput。这些逻辑字体名称以实现相关的方式映射到物理字体。
So in your case, I'd try
所以在你的情况下,我会尝试
Font mono = new Font(parent.getDisplay(), "Monospaced", 10, SWT.NONE);
Font mono = new Font(parent.getDisplay(), "Monospaced", 10, SWT.NONE);
to get a handle to the physical monospaced font of the current platform your code is running on.
获取您的代码正在运行的当前平台的物理等宽字体的句柄。
Edit: It seems that SWT doesn't know anything about logical fonts (Bug 48055on eclipse.org describes this in detail). In this bug report a hackish workaround was suggested, where the name of the physical font may be retrieved from an AWT font...
编辑:SWT 似乎对逻辑字体一无所知(eclipse.org 上的错误 48055对此进行了详细描述)。在此错误报告中,建议了一种骇人听闻的解决方法,其中可以从 AWT 字体中检索物理字体的名称...
回答by Bartleby
I spent a while bashing my head against this one until I realised that obviously eclipse must have access to a monospace font for use in its text fields, console etc. A little digging turned up:
我花了一段时间对这个进行抨击,直到我意识到很明显 eclipse 必须可以访问等宽字体才能在其文本字段、控制台等中使用。一个小小的挖掘出现了:
Font terminalFont = JFaceResources.getFont(JFaceResources.TEXT_FONT);
Which works if all you're interested in is getting hold of some monospace font.
如果您感兴趣的只是获取一些等宽字体,这会起作用。
Edit:Or based on @ctron's comment:
编辑:或基于@ctron 的评论:
Font font = JFaceResources.getTextFont();
Edit:Caveat (based on @Lii's comment): this will get you the configured Text Font, which can be overriden by the user and may not be a monospace font. However, it will be consistent with, e.g., the font used in the editor and console which is probablywhat you want.
编辑:警告(基于@Lii 的评论):这将为您提供配置的文本字体,该字体可以由用户覆盖并且可能不是等宽字体。但是,它将与例如编辑器和控制台中使用的字体保持一致,这可能是您想要的。
回答by McDowell
To the best of my knowledge, the AWT API does not expose underlying Font information. If you can get to it, I would expect it to be implementation dependent. Certainly, comparing the font mapping files in a couple of JRE lib directories, I can see that they are not defined in a consistent way.
据我所知,AWT API 不会公开底层字体信息。如果你能得到它,我希望它依赖于实现。当然,比较几个 JRE lib 目录中的字体映射文件,我可以看到它们的定义方式不一致。
You could load your own fonts, but that seems a little wasteful given you know the platform comes with what you need.
您可以加载自己的字体,但鉴于您知道平台随附您需要的字体,这似乎有点浪费。
This is a hack that loads a JRE font:
这是一个加载 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;
}
It works on IBM/Win32/JRE1.4, Sun/Win32/JRE1.6, Sun/Linux/JRE1.6, but is a pretty fragile approach. Depending on your needs for I18N, it could be trouble there too (I haven't checked).
它适用于 IBM/Win32/JRE1.4、Sun/Win32/JRE1.6、Sun/Linux/JRE1.6,但它是一种非常脆弱的方法。根据您对 I18N 的需求,那里也可能有问题(我还没有检查过)。
Another hack would be to test the fonts available on the platform:
另一个技巧是测试平台上可用的字体:
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();
}
}
}
This probably isn't a good approach as it may leave you exposed to locale issues. Besides, you don't know if the first monospaced font you come across isn't some windings icon set.
这可能不是一个好方法,因为它可能会让您暴露于语言环境问题。此外,您不知道您遇到的第一个等宽字体是否不是一些绕组图标集。
The best approach may just be to take your best guess based on a font/locale mapping whitelist and make sure that the users can easily reconfigure the UI to suit themselves via FontDialog.
最好的方法可能只是根据字体/区域设置映射白名单做出最佳猜测,并确保用户可以通过FontDialog轻松重新配置 UI 以适合自己。
回答by freesniper
For people who have the same problem, you can download any font ttf file, put it in the resource folder (in my case /font/**.ttf) and add this methode to your application. It's work 100 %.
对于有同样问题的人,您可以下载任何字体 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; }
回答by freesniper
If you want just a Monospaced font use "Courier" => new Font(display, "Courier", 10, SWT.NORMAL)
如果您只想要等宽字体,请使用“Courier”=> new Font(display, "Courier", 10, SWT.NORMAL)

