Java 如何更改Swing GTK LookAndFeel中的默认字体大小?

Java 如何更改Swing GTK LookAndFeel中的默认字体大小?,java,swing,gtk,look-and-feel,font-size,Java,Swing,Gtk,Look And Feel,Font Size,有没有办法更改Swing GTK LaF中的默认字体大小 GTK LaF似乎采用72dpi,因此所有字体的大小仅为使用96dpi屏幕时的3/4。请参阅此以了解详细信息。我想在等待修复的同时找到一个解决方法 例如,我已经尝试过按照建议通过UIDefaults重置字体大小,但GTK LaF似乎忽略了这一点 我可以建立一个widget工厂,它还可以设置创建所有Swing widget所需的字体大小,但这将是一个大规模的入侵,因此如果有其他方法,我希望避免这种途径 编辑:以下内容不起作用: public

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

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

例如,我已经尝试过按照建议通过
UIDefaults
重置字体大小,但GTK LaF似乎忽略了这一点

我可以建立一个widget工厂,它还可以设置创建所有Swing widget所需的字体大小,但这将是一个大规模的入侵,因此如果有其他方法,我希望避免这种途径

编辑:以下内容不起作用:

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;
  }
}
公共类GTKLaF扩展com.sun.java.swing.plaf.gtk.gtklook{
@凌驾
公共UIDefaults getDefaults(){
最终浮标度=3f;
最终UIDefaults=super.getDefaults();
最终映射更改=新建HashMap();
对于(Map.Entry e:defaults.entrySet()){
最终对象键=e.getKey();
最终对象val=e.getValue();
如果(val instanceof FontUIResource){
最终FontUIResource值=(FontUIResource)val;
最终FontuinRes=
新的FontUIResource(ores.deriveFont(ores.getSize2D()*scale));
更改。放置(键,nres);
系统输出打印项次(键+“=”+nres);
} 
else if(val instanceof Font){
nt的最终字体=(Font)val;
最终字体nfont=ofont.deriveFont(ofont.getSize2D()*比例);
更改。放置(键,nfont);
System.out.println(键+“=”+nfont);
}
}
默认值。putAll(更改);
返回默认值;
}
}

您可能认为这将打印至少12个键值对,但它只打印一个:TitledBorder.font。显然,其他字体属性不是由GTLLookAndFeel提供的,而是来自其他地方

您链接的代码有问题。
ui默认值。get(key)
函数不必返回
Font
实例。它可能是一个
javax.swing.plaf.FontUIResource
实例。 下面的代码段将查找所有已安装的外观,然后以
比例更改所有字体大小

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示例》第三版中找到了一些关于GTK LaF问题的信息。
看看它

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

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

使用获取当前DPI

int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
如果不是72,您可以相应地更改字体大小


编辑:我认为你发布的链接不起作用,因为GTKLookAndFeel覆盖了所涉及的方法,不允许任何来自其祖先的默认值通过。反过来重写它应该可以避免这个问题。

似乎没有办法设置默认字体大小。然而,问题中提到的bug已经被修复,所以现在还没有必要这么做。

我花了很多时间思考如何在ubuntu上让我们的应用程序变得像样,于是我开始了这项攻略。 我尝试过像有人建议的那样扩展GTKLookAndFeel,但由于它使用了许多对GTKEngine的本地调用,我意识到这是不可行的。 我希望这有帮助

在设置了look-and-feel call my-hack-checklookandfeel()之后,它将字体标准降低了两点:

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样式。
不是很优雅,但很管用

这不管用。对于GTK LaF,它与我设置的比例因子没有任何区别——这段代码没有明显的效果。调用UIManager.getInstalledLookAndFeels()似乎会导致X的灾难性崩溃,不知何故——机器很难锁定。如果我去掉这个和外部循环,你的代码对金属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
中的键。请参阅我对原始问题的编辑。重写
getDefaults()
不起作用,因为键不在那里。伙计,这一定是一个设计糟糕的外观。虽然我没有看源代码,但我开始觉得他们只是硬编码了值。作为最后的手段,你可以把GTKLookAndFeel代码复制到你自己的类中,并在其中添加一些东西。是的,我认为这是一个相当棘手的问题。我给你奖金是因为(1)时间快到了,(2)你最接近一个答案。(我的怀疑是,要正确实现这一点,需要覆盖更多的方法,可能是在
com.sun.java.swing.plaf.gtk
中的其他一些类中)