Как изменить размер шрифта по умолчанию в Swing GTK LookAndFeel? - PullRequest
5 голосов
/ 11 октября 2010

Есть ли способ изменить размер шрифта по умолчанию в Swing GTK LaF?

GTK LaF, похоже, принимает 72dpi, поэтому все шрифты имеют размер только 3/4 от размера, который они должны быть при использовании экрана 96dpi. Подробности смотрите в ошибке Fedora . Тем временем я хотел бы найти обходной путь, пока жду исправления.

Я уже пытался сбросить размер шрифта с помощью UIDefaults, как рекомендовано, например, здесь , но (как и там отмечено) GTK LaF, похоже, игнорирует это.

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

Редактировать: Не работает следующее:

public class GTKLaF extends com.sun.java.swing.plaf.gtk.GTKLookAndFeel {
  @Override
  public UIDefaults getDefaults() {
    final float scale = 3f;

    final UIDefaults defaults = super.getDefaults(); 

    final Map<Object,Object> changes = new HashMap<Object,Object>();

    for (Map.Entry<Object,Object> e : defaults.entrySet()) {
      final Object key = e.getKey();
      final Object val = e.getValue();

      if (val instanceof FontUIResource) {
        final FontUIResource ores = (FontUIResource) val;
        final FontUIResource nres =
          new FontUIResource(ores.deriveFont(ores.getSize2D()*scale));
        changes.put(key, nres);
        System.out.println(key + " = " + nres);
      } 
      else if (val instanceof Font) {
        final Font ofont = (Font) val;
        final Font nfont = ofont.deriveFont(ofont.getSize2D()*scale);
        changes.put(key, nfont);
        System.out.println(key + " = " + nfont);
      }
    }

    defaults.putAll(changes);

    return defaults;
  }
}

Вы могли бы подумать, что это напечатало бы по крайней мере дюжину пар ключ-значение, но это печатает только одну: TitledBorder.font. Очевидно, что другие свойства шрифта не предоставляются GTLLookAndFeel, а получены из другого места!

Ответы [ 4 ]

1 голос
/ 20 октября 2010

Я предлагаю создать свой собственный подкласс GTKLookAndFeel и использовать его.

В вашем подклассе я бы, вероятно, переопределил getDefaults().В вашем getDefaults() вы можете получить UIDefaults, который GTKLookAndFeel собирался вернуть, и настроить их при необходимости.(Оборачивая или разбивая их на подклассы и переопределяя методы UIDefaults.getFont.)

Получите текущий DPI с помощью

int dpi = Toolkit.getDefaultToolkit().getScreenResolution();

, а если это не 72, вы можете соответственно изменить размер шрифта.

Редактировать: ссылка, которую вы разместили, не работает, я думаю, потому что GTKLookAndFeel переопределяет используемые методы и не пропускает никакие значения по умолчанию от своих предков.Переопределение в свою очередь должно позволить вам обойти эту проблему.

1 голос
/ 04 октября 2011

Похоже, нет способа установить размер шрифта по умолчанию. Однако ошибка, упомянутая в вопросе, с тех пор была исправлена, поэтому необходимость сделать это теперь спорная.

0 голосов
/ 10 июля 2015

Я потерял много времени на выяснение того, как сделать наше приложение достойным на Ubuntu, и я пришел к этому хаку. Я пытался, как кто-то предложил расширить GTKLookAndFeel, но так как он использует много собственных вызовов GTKEngine, и я понял, что это не жизнеспособно. Я надеюсь, что это помогает

Сразу после настройки внешнего вида вызовите мой хак checkGTKLookAndFeel (), чтобы уменьшить стандарт шрифта на два пункта:

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
try {
    InvoicexUtil.checkGTKLookAndFeel();
} catch (Exception e) {
    e.printStackTrace();
}

public static void checkGTKLookAndFeel() throws Exception {
    LookAndFeel look = UIManager.getLookAndFeel();
    if (!look.getID().equals("GTK")) return;

    new JFrame();
    new JButton();
    new JComboBox();
    new JRadioButton();
    new JCheckBox();
    new JTextArea();
    new JTextField();
    new JTable();
    new JToggleButton();
    new JSpinner();
    new JSlider();
    new JTabbedPane();
    new JMenu();
    new JMenuBar();
    new JMenuItem();

    Object styleFactory;
    Field styleFactoryField = look.getClass().getDeclaredField("styleFactory");
    styleFactoryField.setAccessible(true);
    styleFactory = styleFactoryField.get(look);

    Field defaultFontField = styleFactory.getClass().getDeclaredField("defaultFont");
    defaultFontField.setAccessible(true);
    Font defaultFont = (Font) defaultFontField.get(styleFactory);
    FontUIResource newFontUI;
    newFontUI = new FontUIResource(defaultFont.deriveFont((float)(defaultFont.getSize() - 2f)));
    defaultFontField.set(styleFactory, newFontUI);

    Field stylesCacheField = styleFactory.getClass().getDeclaredField("stylesCache");
    stylesCacheField.setAccessible(true);
    Object stylesCache = stylesCacheField.get(styleFactory);
    Map stylesMap = (Map) stylesCache;
    for (Object mo : stylesMap.values()) {
        Field f = mo.getClass().getDeclaredField("font");
        f.setAccessible(true);
        Font fo = (Font)f.get(mo);
        f.set(mo, fo.deriveFont((float)(fo.getSize() - 2f)));
    }
}

вызовите конструктор различных компонентов Swing для инициализации стилей GTK. не очень элегантно, но работает

0 голосов
/ 19 октября 2010

Что-то не так с кодом, который вы связали. UIDefaults.get(key) функция не должна возвращать экземпляр Font. Это может быть javax.swing.plaf.FontUIResource экземпляр. Следующий фрагмент кода находит весь установленный внешний вид и изменяет размеры всех шрифтов в соотношении scale

float scale=1.1f;
UIManager.LookAndFeelInfo looks[] = UIManager.getInstalledLookAndFeels();

for (UIManager.LookAndFeelInfo info : looks) {

    //if you want to change LaF to a spesific LaF,such as "GTK"
    //put here a if statement like:
    //if(info.getClassName().contains("GTK"))
    UIManager.setLookAndFeel(info.getClassName());

    UIDefaults defaults = UIManager.getDefaults();
    Enumeration newKeys = defaults.keys();

    while (newKeys.hasMoreElements()) {
        Object obj = newKeys.nextElement();
        Object current = UIManager.get(obj);
        if (current instanceof FontUIResource) {
            FontUIResource resource = (FontUIResource) current;
            defaults.put(obj, new FontUIResource(resource.deriveFont(resource.getSize2D()*scale)));
            // System.out.printf("%50s : %s\n", obj,  UIManager.get(obj));
        } else if (current instanceof Font) {
            Font resource = (Font) current;
            defaults.put(obj, resource.deriveFont(resource.getSize2D()*scale));
            // System.out.printf("%50s : %s\n", obj,  UIManager.get(obj));
        }
    }
}

Я нашел кое-что о проблеме GTK LaF в книге «Примеры Java в двух словах», третье издание. Взгляните на это здесь

...