Ошибка или функция: неверный шрифт Swi по умолчанию для Win6 +
просто (удивительно ;-) заметил причину, по которой приложения выглядят так тесно на моих машинах win6 + (то же самое для Vista и Win7, оба с настройкой 120dpi, jdk6 и jdk7): контрольный шрифт, который выглядел из свойства desktop, имеет неправильный шрифт семья и неправильный размер:
public static void main(String[] args) {
Font guiFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty("win.defaultGUI.font");
int guiSize = guiFont.getSize();
Font iconFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty("win.icon.font");
System.out.println("gui default: " + guiFont + "\nicon default: " + iconFont);
}
выход:
gui default: java.awt.Font[family=Tahoma,name=Tahoma,style=plain,size=13]
icon default: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=15]
Последний используется в нативных приложениях почти для всего текста, тогда как Swing использует первый ...
Вопросы:
Could there be any reason for this, or just a bug? Who's responsible: the Swing lookup (when reading-in the desktopProperty from relevant system resources) or the OS in not reporting it correctly? How to force the usage of the latter?Варианты решения последней:
With full control about the LAF one might consider to set all relevant text fonts (that's what JGoodies does, factored into a FontPolicy/Set). A dirty hack is to set the value of the defaultGUI desktop property to the correct value - it involves reflective access to the toolkit, which naturally will blow in security constrained contexts. ??Edit
На всякий случай, если кому-то интересно, вот грязный хак:
/**
* Replaces the default gui desktop font property with the icon font
* if the former is smaller.
*
*/
public static void ensureDefaultGUIFontSize() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Font guiFont = (Font) toolkit.getDesktopProperty("win.defaultGUI.font");
Font iconFont = (Font) toolkit.getDesktopProperty("win.icon.font");
if (guiFont.getSize() < iconFont.getSize()) {
invokeDeclaredMethod("setDesktopProperty", Toolkit.class,
toolkit, "win.defaultGUI.font", iconFont);
}
}
private static void invokeDeclaredMethod(String methodName,
Class<?> clazz, Object instance, String propertyName,
Object propertyValue) {
try {
Method method = clazz.getDeclaredMethod(methodName, String.class, Object.class);
method.setAccessible(true);
method.invoke(instance, propertyName, propertyValue);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
LOG.finer("forcing desktop property failed " + e.getStackTrace());
}
}
Edit 2
Просто чтобы уточнить: взломать полностью эффективно только для WindowsLAF. Nimbus полностью игнорирует системные настройки, частично Metal: шрифт последнего всегда является Dialog, только размер взят из desktopProperties. Звучит на полпути хорошо, но это не так: отображение довольно странно для основных шрифтов, например. интенсивно используемый размер controlFont установлен на "win.ansiVar.font.height" (что это за остатки ископаемого?), что 13 на моей машине ...
Edit 3
Даже в Windows UI, взлом это ... взлом с ограничениями, например. те, что упоминаются в комментарии @ Walter's:
This bug is especially noticeable when you scale the Windows UI. FYI, opening a JFileChooser reverts the hack. Also JTree/JTable row height will not be automatically updated to the new font size and you'll need to scale your icons as well