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

79
如果您有一个DPI超过150的显示器(比如Macbook Pro),您可能也会发现这个问题:Java Swing应用程序上的字体对于高DPI显示器来说太小了,而我无法改变字体大小(它直接忽略Windows DPI,只显示最初的DPI-->96)。我无能为力,只能改变屏幕分辨率,但这会使LCD上的所有东西都模糊不清。

是的,我有一台带有高DPI显示器的笔记本电脑,15.6英寸,分辨率为1920x1080,一些Java桌面应用程序在我的笔记本电脑上看起来非常小,例如Matlab、Burpsuite等等。我已经在互联网上搜索了很长时间,但仍然找不到解决问题的方法。我知道我可以通过JRE_HOME/lib/font/fontconfig.properties.src更改JRE字体,但我找不到任何地方来设置Java桌面字体的默认字体大小或DPI。

这个问题没有解决方法吗?您有高DPI显示器吗?您如何处理此类应用程序?Swing放弃了高DPI用户吗?


3
这可能会对您有所帮助:这篇文章探讨了如何在不更改屏幕尺寸的情况下设置Java Swing应用程序的DPI分辨率。 - Parth Soni
告诉我们你的结果,这样我们就知道该有多嫉妒了。 :-) - trashgod
离题:如果普通的Windows程序即使在兼容性选项中清除“无DPI缩放”标志时仍无法很好地缩放,那么您可能正在运行64位版本的程序。请尝试使用32位版本。 - Mark Jeronimus
7个回答

41

我目前正在Windows上调查这个问题。以下是我找到的情况:

大多数Swing外观和感觉根本不支持高DPI,即使是被认为是可伸缩的Nimbus也不例外。我找到了一些旧的博客文章说Nimbus可能最终会提供高DPI缩放,但显然这从未发生过。

唯一的例外是系统LAF,但它的默认字体比实际系统字体大小小约10%,在所有DPI设置下都是如此。此外,必须显式选择System,如此处所述: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

在Swing中,没有单一的缩放因子可以设置。具体的外观感觉必须提供处理缩放的代码。所以你能做的最好的办法就是选择System并希望它足够好。

然而,在我的系统上,JavaFX确实可以正确且自动地缩放到150%。如果有可能,我建议你使用JavaFX来构建你的GUI。

编辑:我编写了几个小测试程序,并为各种GUI框架、Swing主题和DPI设置拍摄了比较截图。这对于阅读此问题的人可能是有益的:http://kynosarges.org/GuiDpiScaling.html


17

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

长篇回答:
这是因为Java运行时声称自己是“DPI感知”的,但实际上并没有为AWT和Swing提供真正的支持。Java应用程序基于像素大小进行调整和渲染,而不是正确缩放,这包括HiDPI显示器。 无论如何,这个问题最近已经解决了。 请参见JEP 263:Windows和Linux上的HiDPI图形升级

因此,增加字体大小不起作用(因为它不会增加其他东西);jvm参数-Dsun.java2d.dpiaware=false不起作用(因为它实际上没有得到支持);而清单文件+注册表编辑器(适用于Windows)也不起作用。

解决方案:您需要在JRE 9+上运行它,因为它真正支持此功能。


在Java8中,我通过在manifest文件javaw.exe中切换dpiAware参数得到了帮助。 - MisterParser
嗨@MisterParser,我在哪里可以找到javaw.exe的清单文件? - Pubudu Mahesh Meththananda

11

这个答案解决了我在4K屏幕上使用Ubuntu笔记本的问题。

在应用程序的配置文件中,我添加了-Dsun.java2d.uiScale=2.5 Java参数,现在,执行应用程序时,它被缩放得很好并且可以正常使用。


1
这对我有所帮助,可以重新调整建模应用程序“NetLogo”的显示:将"java-options=-Dsun.java2d.uiScale=3"添加到文件lib/app/NetLogo.cfg中。但是,它必须是Netlogo 6.3.0或更高版本。 - knb
这里也一样:NetLogo 6.3.0,Linux Mint 21.1。感谢 @Pascal! - A Koscianski

5

看起来在Linux(Gtk)上,您可以通过在启动应用程序之前使用以下方法缩放应用程序的DPI来解决此问题。

export GDK_SCALE=2

(您也可以降低您的显示器分辨率,但那不是解决方案。)

1
当我在Ubuntu 20.04的snap中运行应用程序时,我无法修改Bash脚本以添加JVM选项。不过你的建议完美地解决了这个问题。谢谢! - Takis
1
这个可以运行,但不支持分数缩放。因此,对于我的1920*1080屏幕来说,文本太大了。 - javaEntu
是的,这绝对不是一个好的解决方案,但我想总比没有强。 - demented hedgehog

3
在Linux系统中,根据我的实验结果,似乎无法使用任何Swing外观进行缩放。但是,可以通过使用涉及VNC的黑客技巧,如vncdesk,来实现缩放。以下是我在vncdesk下运行gradle --gui的配置信息:

.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 "$@"

这种情况下,最小化的 matchbox-window-manager 是理想的选择。 - Quoting Eddie

2

我成功地按照这些指示解决了问题:链接

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

创建这个注册表键:

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

创建一个包含以下内容的清单文件:
<?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 (您将拥有两个具有相同内容但不同名称的文件)。

希望对您有所帮助。

Bernd


遗憾的是,这对我似乎没有任何改变。我正在运行32位Java,但我不知道我是否有选择,如果有区别的话。编辑:实际上,在我的情况下,问题可以解决,至少是通过为有问题的单个应用程序创建清单,而不是java / javaw.exe。请参见http://javahacker.com/eclipse-on-a-high-dpi-display-in-windows/。 - Alex Whittemore
1
@AlexWhittemore 阅读了相关文章后,我必须说,这正是它所建议的 - 创建<Application>.exe.manifest文件以禁用DPI缩放。这与eferrari所说的不同。 - Dimitar
@user8 我从来没有跟进,但是是的,这个链接完全如此描述,发现得好 ;) - Alex Whittemore
这个解决方案貌似只适用于Windows操作系统? - Michael Scheper
没有配置注册表键的情况下,有没有解决此问题的选项? - Pubudu Mahesh Meththananda

1
如@demented hedgehog所说,在Linux下设置GDK_SCALE=2环境变量是有效的。
如果您使用JetBrains IntelliJ,您可以在“编辑配置>构建和运行>环境变量”下为您的项目设置环境变量。
您可以看到下面在哪里放置GDK_SCALE=2。

IntelliJ: Setting an environment variable.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接