2010-10-11 146 views
5

有没有办法在Swing GTK LaF中更改默认字体大小?如何更改Swing GTK LookAndFeel中的默认字体大小?

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不提供其他字体属性,但是来自其他地方!

回答

1

似乎没有办法设置默认字体大小。然而,问题中引用的bug后来得到了修复,所以现在需要做这个工作。

0

您链接的代码有问题。 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实例的比率。 看看吧here

+0

这是行不通的。对于GTK LaF,对于我设置比例因子的内容没有什么区别---这个代码没有明显的效果。 – uckelman 2010-10-19 19:55:21

+0

@uckelman它是否适用于其他LaF? – 2010-10-19 20:02:46

+0

对UIManager.getInstalledLookAndFeels()的调用似乎会导致X的灾难性崩溃,不知何故---机器会很难锁定。如果我删除这个和外部循环,你的代码对Metal LaF来说是有效的。 – uckelman 2010-10-19 20:43:59

1

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

在你的子类中,我可能会覆盖getDefaults()。在您的getDefaults()中,您可以获取GTKLookAndFeel将要返回的UIDefaults,并在必要时调整它们。 (通过包装或继承他们重写UIDefaults.getFont方法。)

获取当前DPI与

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

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

编辑:您发布的链接不起作用,我相信因为GTKLookAndFeel会覆盖所涉及的方法,并且不会让其祖先的任何默认值通过。重写它反过来应该允许你绕过这个问题。

+0

请参阅我对原始问题的编辑。重写'getDefaults()'不起作用,因为键不在那里。 – uckelman 2010-10-20 21:32:38

+0

男人,这必须是一个设计不好的外观。虽然我没有看过源代码,但我开始觉得他们只是硬编码了这些值。作为最后的手段,你可以将GTKLookAndFeel代码复制到你自己的类中,然后在其中加入一些东西。 – 2010-10-20 21:59:29

+0

是的,我认为这是一堆热气腾腾的东西。我给了你赏金,因为(1)时间快到了,(2)你最接近答案。 (我怀疑得到这个权利将需要重写更多的方法,可能在'com.sun.java.swing.plaf.gtk'中的其他类中。) – uckelman 2010-10-21 16:02:55

0

我花了很多时间搞清楚如何让我们的应用在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风格。 不是很优雅,但它的作品