Windows GUI DPI Scaling in 2018

I have updated the article DPI Scaling in Windows GUIs with a modified test suite and new sets of screenshots for Windows 10 Creators Update, Microsoft .NET Framework 4.7.1, and Oracle Java SE 9.0.4. The focus of this update was of course Java 9 as JavaFX ceased special-casing 120 DPI, and AWT/Swing even got full automatic coordinate scaling for the first time. However, I also wanted to check whether .NET 4.7’s high DPI improvements for Windows Forms would affect my test suite (spoiler: they didn’t).

Below is a sample of the test suite at 120 DPI for WPF, JavaFX, and Swing. JavaFX 120a (with fixed column widths) no longer cuts off control labels as in Java 8, and Swing 120d has become veritably useful (more obvious at higher resolutions) aside from the unfortunate Sans Serif font.

I also added a new section on obtaining the current scaling factor. This is pretty simple in WPF and JavaFX in Java 9 but rather convoluted for AWT/Swing, unless I missed a simpler method.

I removed my brief overview of JavaFX from the article. It was originally intended to inform WPF developers about this mysterious new Java thing. By now JavaFX is fairly well known, and the article had already grown too long with the new sets of screenshots.

There is one very important note on a new JavaFX bug, though. Below is the full description as far as I could figure it out.

JavaFX: Truncated Labels

When I re-ran the test suites on 120 DPI (= 125%) and 144 DPI (= 150%) in Java 9, I found to my horror that the “Check” label of the CheckBox in the lower left was truncated with an ellipsis. This happened at both scales without the autoGrid test option (i.e. explicit column widths), and still at 125% even with this option (i.e. automatic column sizing). Testing some more, the label was once again cut off at 175% with or without autoGrid. On 100% or 200% everything was fine, though.

The following screenshot shows the appearance of the 120 DPI test case withautoGrid before I artificially suppressed the error (see below). Not only the CheckBox label but also the adjacent Button label is truncated! This absolutely should not happen. (The screenshot was taken at a Windows DPI scale of 200% but running Java with -Dglass.win.uiScale=125%, hence the oversized non-client area.)

I checked my real JavaFX applications at 125% and 150% but to my relief found no display issues. However, the bug is very real and can be easily reproduced. My present guess is that on DPI scales that are not multiples of 100%, there is a small discrepancy in the initial measurement between a label’s required width and the width provided by its container. In complex windows this gets eventually fixed by subsequent layout passes, but in simple windows like my test suite the error persists and manifests as an ellipsis.

I posted a description of the bug with reproducing code to the JavaFX mailing list (update: see below). Since the bug doesn’t seem to surface in real applications it’s not quite as serious as I originally thought but it’s still pretty bad. For example, any newcomer to JavaFX seeing an inexplicably cut-off label in his first simple test window would probably just walk away (to Swing Nimbus maybe?).

2018-03-14: As per Kevin Rushforth’s suggestion on the mailing list I filed a proper bug report with Oracle which is now public as JDK-8199592. It’s a regression introduced in Java SE 9 build 114 that persists in the current Java SE 11 development build.

Suppressing the Bug

You will have noticed that this bug does not appear in the test suite screenshot. That’s because I added a hack to the JavaFX test program, forcing the minimum width of the CheckBox to the nearest integer of its reported automatic layout width. That turned out to be sufficient to prevent the ellipsis truncation – interestingly also for the adjacent Button label.

Why suppress the bug rather than show it in the screenshots? Isn’t that cheating? I thought about that for a while but eventually came down on the side of hiding (but obviously documenting!) this particular bug for the following reasons.

It’s really just a bug, not a display error by design as the truncated labels in the Java 8 version of JavaFX 120a where full scaling was deliberately disabled. The article is meant to show the intended scaling behavior of GUI frameworks, not peculiar bugs.

Specific DPI scales are required but not sufficient conditions for the bug. As noted above it only seems to appear in very simple layouts, such as my test suite. So in addition to being unintended it’s a bug that generally does not manifest in real applications.

That said, I certainly hope the bug will get fixed soon. I’ll update this post and the article once that happens.