【问题标题】:How to change the default font size in the Swing GTK LookAndFeel?如何更改 Swing GTK LookAndFeel 中的默认字体大小?
【发布时间】:2011-04-23 20:25:48
【问题描述】:

有没有办法改变 Swing GTK LaF 中的默认字体大小?

GTK LaF 似乎假定为 72dpi,因此所有字体的大小仅为使用 96dpi 屏幕时应有的大小的 3/4。有关详细信息,请参阅此Fedora bug。在等待修复的同时,我想找到一种解决方法。

我已经尝试通过UIDefaults 重置字体大小,例如推荐的here,但是(也如那里所述)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 提供的,而是来自其他地方!

【问题讨论】:

    标签: java swing gtk look-and-feel font-size


    【解决方案1】:

    您链接的代码有问题。UIDefaults.get(key) 函数不必返回Font 实例。它可能是一个javax.swing.plaf.FontUIResource 实例。 以下代码 sn-p 查找所有已安装的外观,然后以 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));
            }
        }
    }
    

    我在一本书,Java Examples in a Nutshell, Third Edition 中找到了一些关于 GTK LaF 问题的内容。 看看吧here

    【讨论】:

    • 这不起作用。对于 GTK LaF,这与我设置的比例因子没有区别——这段代码没有明显的效果。
    • 对 UIManager.getInstalledLookAndFeels() 的调用似乎导致了 X 的灾难性崩溃,不知何故 --- 机器死锁了。如果我删除它和外循环,您的代码确实适用于 Metal LaF。
    • 答案已更新,答案底部有一个链接,解释了 GTK 问题。请尝试一下,让我知道它是否有效。
    • 该链接是关于确保系统了解 GTL LaF。这不是我面临的问题。当我使用-Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel 设置运行时,我确实将 GTK LaF 作为安装的 LaF。在这种情况下,UIManager.getSystemLookAndFeelClassName() 返回com.sun.java.swing.plaf.gtk.GTKLookAndFeel。问题是 GTK LaF 只是忽略了我放入 UIManager 的键。
    【解决方案2】:

    我的建议是创建您自己的 GTKLookAndFeel 子类并使用它。

    在您的子类中,我可能会覆盖 getDefaults()。在您的getDefaults() 中,您可以获得GTKLookAndFeel 将返回的UIDefaults,并在必要时对其进行调整。 (通过包装或子类化它们并覆盖UIDefaults.getFont 方法。)

    使用

    获取当前 DPI
    int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
    

    如果不是 72,你可以相应地更改字体大小。

    编辑:我相信您发布的链接不起作用,因为 GTKLookAndFeel 覆盖了所涉及的方法,并且不允许其祖先的任何默认值通过。依次覆盖它应该可以让你规避这个问题。

    【讨论】:

    • 查看我对原始问题的编辑。覆盖 getDefaults() 不起作用,因为密钥不存在。
    • 伙计,这一定是一种设计不佳的外观。虽然我没有查看源代码,但我开始觉得他们只是对值进行了硬编码。作为最后的手段,您可以将 GTKLookAndFeel 代码复制到您自己的类中并破解一些东西。
    • 是的,我认为这是一堆热气腾腾的东西。我给你赏金是因为(1)时间快到了,(2)你最接近答案。 (我怀疑要做到这一点需要重写更多方法,可能在com.sun.java.swing.plaf.gtk 的其他一些类中。)
    【解决方案3】:

    似乎无法设置默认字体大小。但是,问题中提到的错误已经被修复,所以现在需要这样做没有实际意义。

    【讨论】:

      【解决方案4】:

      我浪费了很多时间来弄清楚如何在 ubuntu 上让我们的应用程序体面,我来到了这个 hack。 我曾尝试过有人建议扩展 GTKLookAndFeel,但由于它使用了许多对 GTKEngine 的本机调用,我意识到它不可行。 我希望这会有所帮助

      在设置外观和感觉之后调用我的 hack 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 样式。 不是很优雅,但很有效

      【讨论】:

        猜你喜欢
        • 2017-04-01
        • 2013-06-11
        • 1970-01-01
        • 2012-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-28
        • 2012-06-12
        相关资源
        最近更新 更多