79

If you have an monitor with a DPI over 150 (such as Macbook Pro), you may also find the problem: the font on the Java Swing app is too small for high DPI monitor, and I cannot change the font size at all ( It ignores the Windows DPI directly, only displaying the very original DPI-->96 ). I can do nothing but changing the screen resolution, which could absolutely make everything blurry on LCD.

Yes, I have a laptop with a high DPI monitor, 15.6' with 1920x1080 resolution, some Java desktop apps look very small on my laptop, such as Matlab, Burpsuite etc. I have been searching the Internet for a very very long time, but still cannot find a method for the problem. I know I can change the JRE fonts through JRE_HOME/lib/font/fontconfig.properties.src, but I cannot find any place to set the default font size or DPI for Java desktop fonts.

Does the problem have no solution? Do you have a high DPI monitor? How do you do with such apps? Does Swing give up high DPI users?

Lii
  • 11,553
  • 8
  • 64
  • 88
Searene
  • 25,920
  • 39
  • 129
  • 186
  • 3
    [This](http://stackoverflow.com/questions/1102216/can-i-set-the-dpi-resolution-of-my-java-swing-application-without-changing-the-s) might help you – Parth Soni Mar 27 '13 at 12:46
  • And [tell us your results](http://meta.stackexchange.com/q/17463/163188), so we know how jealous to be. :-) – trashgod Mar 27 '13 at 13:51
  • Off-topic: If normal windows programs don't scale well, even when you claer the "no DPI scaling" flag in the compatibility options, you're probably running a 64-bit version of the program. Try the 32-bit version instead. – Mark Jeronimus Jan 31 '17 at 09:51

7 Answers7

41

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

17

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.

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196
Sergio Muriel
  • 1,039
  • 9
  • 15
10

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.

Pascal
  • 606
  • 7
  • 15
  • 1
    This helped me for rescaling the display of the modeling-app "NetLogo": appending "`java-options=-Dsun.java2d.uiScale=3` to fille `lib/app/NetLogo.cfg`. It must be Netlogo 6.3.0 or higher, however. – knb Nov 29 '22 at 13:32
  • Same thing here: Netlogo 6.3.0, Linux Mint 21.1. Thanks @Pascal! – A Koscianski Jul 19 '23 at 23:47
5

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).

demented hedgehog
  • 7,007
  • 4
  • 42
  • 49
  • 1
    As I was running an application within a snap on Ubuntu 20.04, I couldn't modify the Bash-script to add the JVM options. Your suggestion works perfectly though. Thanks! – Takis Apr 07 '21 at 08:50
  • 1
    This works, but fractional scaling is not supported. So the text was too big for my 1920*1080 screen. – javaEntu Jun 21 '21 at 21:48
  • Yeah.. it's certainly not a nice solution, but better than nothing I suppose. – demented hedgehog Feb 21 '22 at 22:53
3

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 "$@"
Robin Green
  • 32,079
  • 16
  • 104
  • 187
2

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

Dimitar
  • 4,402
  • 4
  • 31
  • 47
eferrari
  • 21
  • 1
  • Sadly, this didn't seem to change anything for me. I AM running 32 bit java, not that I'm aware I had a choice, if that makes a difference. EDIT: In fact, the problem CAN be solved, at least in my case, by creating a manifest for the individual app that's an issue, rather than java/javaw.exe. Per http://javahacker.com/eclipse-on-a-high-dpi-display-in-windows/ – Alex Whittemore Jan 10 '17 at 15:20
  • 1
    @AlexWhittemore Having read the linked article, I have to say, that, this is exactly what it advises - to create `.exe.manifest` file to disable the DPI Scaling. Different from what eferrari said. – Dimitar Jan 15 '17 at 11:50
  • @user8 I never did follow up, but yes, the link totally does say that, good catch ;) – Alex Whittemore Mar 07 '17 at 00:22
  • It looks like this solution only applies to Windows? – Michael Scheper Jun 04 '19 at 23:07
  • without configuring the registry key, is there a option to solve this issue? – Pubudu Mahesh Meththananda Aug 06 '19 at 11:32
1

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.

Samuel
  • 388
  • 5
  • 15