I just updated my comparison of DPI Scaling in Windows GUIs for the recently released Java SE 8 Update 60 which brought automatic coordinate scaling for JavaFX on Windows at high DPI settings. I had previously only checked that the 200% (192 DPI) setting I’m using on my Dell XPS 15 works correctly. Now I looked at lower DPI settings, namely 125% (120 DPI) and 150% (144 DPI) in addition to the standard scale of 100% (96 DPI).
Special-Cased 120 DPI
The 120 DPI test was good for a surprise: JavaFX 8u60 special-cases this resolution and does not automatically scale all drawing coordinates, as on 144 DPI and above. So you still have to manually scale your layout at this resolution, or at least test your layout to ensure it’s spacious enough to accommodate the larger system default font and accordingly sized controls.
I seem to recall this was mentioned on the OpenJFX mailing list some months back. The reasoning went that 125% is an awkward multiple of 100% that could easily lead to blurry lines and misplaced pixels when coordinates were scaled automatically, but on the other hand the size difference is not so large as to entirely wreck the layout. Sadly I didn’t save a link to this post, perhaps a reader can provide it?
At any rate, this idea appears to have been implemented although Jim Graham’s comment from 22nd May in the JavaFX issue tracker seems to indicate otherwise. Personally I’d rather have consistent behavior and identical layouts throughout all DPI settings, even at the price of some visual quality. If you must specifically target 120 DPI you could still use Swing, after all – both the System and Nimbus Large look & feel work well at that resolution. What are the thoughts of other JavaFX users?
2015-10-25: As the first comment below notes, the actual cause was blurry text at 120 DPI with the new DPI scaling mechanism enabled. Fortunately there’s a simple workaround obvious from this changeset: manually supply the flag
glass.win.minHiDPI to enable the new scaling at all DPI settings. Make sure to use exact capitalization or the flag will be ignored! Example:
java -jar -Dglass.win.minHiDPI=1 Application.jar
At higher DPI settings, I encountered the opposite problem: automatic coordinate scaling is too thorough! Specifically, it’s used even for window coordinates relative to the desktop (
Stage.setX/Y etc.). So when I try to position a window at (100, 100) and DPI scaling is set to 150% it will end up at (150, 150). Worse, there doesn’t appear to be any (official, public) way to determine the current DPI resolution.
In my test package, I worked around this issue by manually supplying the unscaled monitor width on the command line and then determining the DPI scale by comparing against the width reported by the
Screen class. But that’s obviously a temporary hack. Windows positioning should not scale in my opinion (that’s what WPF does), but anyway we need a proper way to see at which DPI setting we’re running.
2015-10-25: And now I discovered the opposite problem: the maximum and minimum sizes of a
Stage are never scaled, at any DPI! This renders
Stage.setMin/MaxWidth/Height effectively useless and is definitely a bug. At least the explicit size properties (
Stage.setWidth/Height) are correctly scaled.