SWT — независимый от ОС способ получить моноширинный шрифт
Вопрос
Есть ли в SWT способ просто получить моноширинный шрифт, который работает в различных операционных системах?
Например.это работает в Linux, но не в Windows:
Font mono = new Font(parent.getDisplay(), "Mono", 10, SWT.NONE);
или мне нужен метод, который пытается загружать различные шрифты (Consolas, Terminal, Monaco, Mono), пока один из них не станет нулевым?В качестве альтернативы я мог бы указать это в файле свойств при запуске.
Я попытался получить системный шрифт от Display, но он не был моноширинным.
Решение
Согласно разделу файлов конфигурации шрифтов в документации JDK API поддержки интернационализации концепция логического шрифта используется для определения определенных платформенно-независимых шрифтов, которые отображаются на физические шрифты в файлах конфигурации шрифтов по умолчанию:
Платформа Java определяет пять логических имен шрифтов, которые должна поддерживать каждая реализация: Serif, SansSerif, Monospaced, Dialog и DialogInput. Эти логические имена шрифтов отображаются на физические шрифты в зависимости от реализации.
Так что в вашем случае я бы попробовал
Font mono = new Font (parent.getDisplay (), " Monospaced " ;, 10, SWT.NONE);
чтобы получить указатель на физический моноширинный шрифт текущей платформы, на которой работает ваш код.
Изменить . Похоже, что SWT ничего не знает о логических шрифтах ( Ошибка 48055 на eclipse.org описывает это подробно). В этом отчете об ошибке был предложен хакерский обходной путь, при котором имя физического шрифта можно извлечь из шрифта AWT ...
Другие советы
Я провел некоторое время, стуча головой по этому, пока не понял, что очевидно, что у eclipse должен быть доступ к моноширинному шрифту для использования в его текстовых полях, консоли и т. д. Небольшое копание обнаружилось:
Font terminalFont = JFaceResources.getFont(JFaceResources.TEXT_FONT);
Что работает, если все, что вас интересует, - это получить какой-то моноширинный шрифт.
Изменить: Или на основе комментария @ ctron:
Font font = JFaceResources.getTextFont();
Edit: Caveat (на основе комментария @ Lii): это даст вам настроенный текстовый шрифт, который может быть переопределен пользователем и не может быть моноширинным шрифтом. Однако это будет соответствовать, например, шрифту, используемому в редакторе и консоли, который вероятно вам нужен.
Насколько мне известно, AWT API не предоставляет информацию о шрифтах. Если вы можете добраться до него, я ожидаю, что это будет зависеть от реализации. Конечно, сравнивая файлы сопоставления шрифтов в паре каталогов lib JRE, я вижу, что они не определены согласованным образом.
Вы можете загрузить свои собственные шрифты, но это кажется немного расточительным, если вы знаете, что платформа поставляется с тем, что вам нужно.
Это хак, который загружает шрифт 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 .
Для людей, у которых такая же проблема, вы можете скачать любой 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; }
Если вы хотите использовать только моноширинный шрифт, используйте " Courier " = & GT; новый шрифт (отображение, «Курьер», 10, SWT.NORMAL)