如何在Windows / Linux上设置Java Swing应用程序的DPI?

如果您的显示器的DPI超过150(如Macbook Pro),您也可能会发现问题: Java Swing应用程序的字体对于高DPI显示器来说太小 ,我根本无法更改字体大小直接忽略Windows DPI,只显示非常原始的DPI – > 96 )。 我无能为力,只能改变屏幕分辨率,这绝对会使LCD上的一切变得模糊。

是的,我有一个高DPI显示器的笔记本电脑,15.6'分辨率为1920×1080,一些Java桌面应用程序在我的笔记本电脑,如Matlab,Burpsuite等看起来很小,我一直在search互联网很长一段时间,但仍然找不到解决问题的方法。 我知道我可以通过JRE_HOME/lib/font/fontconfig.properties.src来更改JRE字体,但是我找不到任何地方为Java桌面字体设置默认字体大小或DPI。

问题没有解决办法吗? 你有一个高DPI显示器? 你如何做这样的应用程序? Swing是否放弃高DPI用户?

我目前正在Windows上调查这个问题。 这是我发现的:

大多数Swing Look&Feels根本不支持高DPI,甚至不支持Nimbus,尽pipe它应该是可扩展的。 我发现一些旧的博客文章说,Nimbus最终可能会提供高DPI的缩放,但显然这从来没有发生过。

系统LAF是一个例外,但是在所有DPI设置下,其默认字体比实际系统字体大小小10%。 此外,系统必须按照此处所述进行显式select: http : //docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

在Swing中也没有单一的缩放因子。 具体的LAF必须提供处理缩放的代码。 所以你可以做的最好的是select系统,希望它足够好。

但是,JavaFX可以在我的系统上正确自动扩展到150%。 如果可能的话,我build议你使用JavaFX来构build你的GUI。

编辑:我做了一些小testing程序,并为各种GUI框架,Swing主题和DPI设置比较截图。 这可能是阅读这个问题的人们的信息: http : //kynosarges.org/GuiDpiScaling.html

你可以像这样修改字体

 public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } setDefaultSize(24); JFrame frame = new JFrame("Testing frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JLabel("Hello world")); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public static void setDefaultSize(int size) { Set<Object> keySet = UIManager.getLookAndFeelDefaults().keySet(); Object[] keys = keySet.toArray(new Object[keySet.size()]); for (Object key : keys) { if (key != null && key.toString().toLowerCase().contains("font")) { System.out.println(key); Font font = UIManager.getDefaults().getFont(key); if (font != null) { font = font.deriveFont((float)size); UIManager.put(key, font); } } } } 

}

使用相同的方法来增加或减less不同布局的字体

根据我的实验, 在Linux上 ,似乎不可能用Swing的外观进行缩放。 但是,可以使用涉及VNC的vncdesk进行破解。 这是我在gradle --gui下运行gradle --guiconfiguration:

.vncdesk/1/settings.ini

 [desktop] width = 1050 height = 650 [window] title = gradle name = gradle in vncdesk class = GradleInVncdesk scale_factor = 2 

.vncdesk/1/startup

 #!/bin/sh cd "$INVOCATION_DIR" matchbox-window-manager& exec gradle --gui "$@" 

简短的回答:您需要在JRE 9上运行它。

很长的回答:
这是因为Java运行时声明自己是“DPI感知的”,但并没有真正支持AWT和Swing。 Java应用程序的大小和渲染基于像素,而不是正确缩放,这包括HiDPI显示。 无论如何,这是最近解决。 在Windows和Linux上查看问题JEP 263:HiDPIgraphics和升级 。

所以,增加字体大小是行不通的(因为它不会增加剩下的东西)。 jvm参数-Dsun.java2d.dpiaware=false不起作用(因为它不是真的支持); 和清单文件+registry编辑(对于Windows)不起作用。

解决scheme:您需要在JRE 9上运行它,因为它确实支持此function。

我设法解决它遵循这些指示: 链接 。

这是德语,但我会翻译重要的东西。

创build这个registry项:

 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide] "PreferExternalManifest"=dword:00000001 

用这个内容创build一个清单文件:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"> </assemblyIdentity> </dependentAssembly> </dependency> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b"> </assemblyIdentity> </dependentAssembly> </dependency> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> <asmv3:application> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware> </asmv3:windowsSettings> </asmv3:application> </assembly> 

将其复制到java.exe和javaw.exe所在的bin目录中,并将其命名为java.exe.manifestjavaw.exe.manifest (您将拥有两个具有相同内容但名称不同的文件)。

HTH。

贝恩德