SWT - ОС независимый способ получить моноширинный шрифт - PullRequest
27 голосов
/ 21 октября 2008

Есть ли способ в SWT просто получить моноширинный шрифт, который работает в различных операционных системах?

Например. это работает в Linux, но не в Windows:


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

или мне нужен метод, который пытается загружать различные шрифты (Consolas, Terminal, Monaco, Mono), пока один из них не станет нулевым? В качестве альтернативы я мог бы указать это в файле свойств при запуске.

Я пытался получить системный шрифт из Display, но он не был моноширинным.

Ответы [ 5 ]

37 голосов
/ 27 февраля 2012

Я провел некоторое время, стуча головой по этому, пока не понял, что, очевидно, у eclipse должен быть доступ к моноширинному шрифту для использования в его текстовых полях, консоли и т. Д. Небольшое копание оказалось:

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

Что работает, если все, что вас интересует, - это получить какой-нибудь моноширинный шрифт.

Редактировать: Или на основе комментария @ ctron:

Font font = JFaceResources.getTextFont();

Редактировать: Предостережение (на основе комментария @ Lii): это даст вам настроенный текстовый шрифт, который может быть переопределен пользователем и не может быть моноширинным шрифтом. Однако это будет соответствовать, например, шрифту, используемому в редакторе и консоли, который вероятно , что вы хотите.

15 голосов
/ 21 октября 2008

Согласно разделу Файлы конфигурации шрифтов в документации JDK Поддержка интернационализации * API 1004 *, концепция Логический шрифт s используется для определения некоторые независимые от платформы шрифты, которые отображаются на физические шрифты в файлах конфигурации шрифтов по умолчанию:

Платформа Java определяет пять логических имен шрифтов, которые должна поддерживать каждая реализация: Serif, SansSerif, Monospaced, Dialog и DialogInput. Эти логические имена шрифтов отображаются на физические шрифты в зависимости от реализации.

Так что в вашем случае я бы попробовал

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

чтобы получить представление о физическом моноширинном шрифте текущей платформы, на которой работает ваш код.

Редактировать : Похоже, что SWT ничего не знает о логических шрифтах ( Ошибка 48055 на eclipse.org описывает это подробно). В этом сообщении об ошибке был предложен хакерский обходной путь, при котором имя физического шрифта можно извлечь из шрифта AWT ...

4 голосов
/ 22 октября 2008

Насколько я знаю, API-интерфейс AWT не предоставляет информацию о шрифтах. Если вы можете добраться до него, я ожидаю, что это будет зависеть от реализации. Конечно, сравнивая файлы сопоставления шрифтов в паре каталогов 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 .

3 голосов
/ 07 марта 2013

Для людей с такой же проблемой вы можете скачать любой файл шрифта 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;   }
1 голос
/ 11 декабря 2008

Если вы хотите просто моноширинный шрифт, используйте "Courier" => new Font(display, "Courier", 10, SWT.NORMAL)

...