如何在 Windows/Linux 下设置 JavaSwing 应用程序的 DPI?

如果你的显示器 DPI 超过150(比如 Macbook Pro) ,你可能会发现问题: Java Swing 应用程序上的字体对于高 DPI 显示器来说太小了,而且我根本不能改变字体大小(它直接忽略 Windows DPI,只显示 最初的新闻部)。我什么也做不了,只能改变屏幕的分辨率,这绝对可以使一切模糊的液晶显示器。

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

这个问题没有解决办法吗?你有一个高分辨率的显示器吗?你如何处理这些应用程序?Swing 会放弃高 DPI 用户吗?

59504 次浏览

I'm currently investigating this issue on Windows. Here's what I found:

Most Swing Look & Feels don't support high DPI at all, not even Nimbus even though it's supposed to be scalable. I found some old blog posts saying that Nimbus might eventually offer high DPI scaling, but apparently that never happened.

The one exception is System LAF but its default font is ~10% smaller than the actual system font size, at all DPI settings. Moreover, System must be selected explicitly as described here: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

There's no single scaling factor that you could set in Swing, either. The specific LAF has to provide code to handle scaling. So the best you can do is select System and hope it's good enough.

However, JavaFX does correctly and automatically scale all the way up to 150% on my system. If at all possible, I suggest you use JavaFX to build your GUI.

edit: I made a couple small test programs and took comparison screenshots for various GUI frameworks, Swing themes, and DPI settings. This might be informative for people reading this question: http://kynosarges.org/GuiDpiScaling.html

On Linux, it doesn't seem possible to do scaling with any Swing look and feel, according to my experiments. However, it is possible to do it using a hack involving VNC, vncdesk. Here is my configuration for running gradle --gui under vncdesk:

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

I managed to solve it following these instructions: Link.

It's in German, but I will translate the important stuff.

Create this registry-key:

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

Create a manifest file with this content:

<?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>

Copy it into the bin directory where the java.exe and javaw.exe is inside and named it java.exe.manifest and javaw.exe.manifest (You will have two files with the same content but different names).

HTH.

Bernd

Short answer: You need to run it on JRE 9+.

Long answer:
This is because the Java runtime declared itself to be "DPI-aware" but didn't really supported it for AWT and Swing. Java applications were sized and rendered based on pixels rather than being properly scaled, this included HiDPI displays. Anyways, this has been recently solved. See the issue JEP 263: HiDPI Graphics on Windows and Linux and the upgrade.

So, increasing the font size does not work (because it does not increase the rest of the things); the jvm argument -Dsun.java2d.dpiaware=false does not work (because it is not really supported); and the manifest file + registry edit (for Windows) just does not work.

Solution: You need to run it on JRE 9+ because it really supports this feature.

This answer solved the issue on my 4K-screen Ubuntu laptop.

In the application's config file, I added the -Dsun.java2d.uiScale=2.5 Java parameter and now, upon executing, the application is scaled well and is usable.

It appears that on Linux (Gtk) you can work around this by scaling the Apps DPI using the following before starting the app.

export GDK_SCALE=2

(You can also reduce you monitor resolution but that's no solution at all).

As @demented hedgehog said setting the GDK_SCALE=2 environment variable does work under Linux.

If you are using JetBrains IntelliJ you can set Enviroment variables just for your project under Edit configurations > Build and Run > Enviroment variables

You can see below where to put the GDK_SCALE=2.

IntelliJ: Setting an environment variable.