JavaFX DPI Scaling in Java 9

While porting my projects to Java SE 9 I noticed that the JavaFX team has slipped in some small but important changes concerning DPI scaling that appear to be only documented in the Java bug database, specifically JDK Bug 8091832.

  • The entry for 2016-03-31 notes that the startup flag, defining the minimum display DPI setting for full (not just font-only) JavaFX DPI scaling, has been removed as it conflicted with per-monitor DPI support.
  • The same entry notes that the startup flag is still supported, so you could use to force full JavaFX DPI scaling at 120 DPI (= 125%) where JavaFX used to only scale fonts, even after Java SE 8u60.
  • However, an entry for 2016-04-06 states that a “fix brings the rest of the graphics into line with the font size” at 120 DPI, meaning that setting is no longer special-cased and now receives full DPI scaling too. No startup flag should be necessary anymore.
  • We can finally determine the current DPI scaling, in both the Screen class (getOutputScaleX/Y) and the Window class (outputScaleX/Y).
  • Even better, the Window class got writable scaling properties (renderScaleX/Y, forceIntegerRenderScale) so you can override DPI scaling on a per-window basis. (The similar startup flags were removed, as noted in the entry for 2016-03-31).
    Note — This feature is unfortunately less useful than I had hoped for. See the comments for an explanation.
  • Unrelated to the linked bug, the min/maxWidth and min/maxHeight properties of the Stage class are now correctly DPI-scaled, so you can properly use them to restrict window resizing.

Very good news! Some older blog posts I wrote on these subjects are now happily obsolete, namely JavaFX GUI Scaling at 120-144 DPI and parts of JavaFX and JAVA_TOOL_OPTIONS. I’m not sure if the mentioned flag -Dprism.order=sw to force software rendering still works, but so far I haven’t seen anything to the contrary.

3 thoughts on “JavaFX DPI Scaling in Java 9”

  1. Hi Christoph,
    Thanks for your post, very useful! I must be missing something though: I tried applying renderScaleX/Y to a scene, but it didn’t change the actual output rendering (only in the buffer, as per the javadoc?). I’ve spent the last hour trying to figure out, how I can actually set the applications scale, but so far I only found the “settings set org.gnome.desktop.interface scaling-factor ‘1’” property to impact the output scale on Linux.

    Am I missing something? Can the scale be really set a per window basis?


    1. Thanks for your comment. I had not experimented with this feature before writing the post, and it turns out I was a bit premature. First of all, the renderScale properties do in fact work. Note that you must set them within a listener binding to outputScale as noted in the API docs, or else JavaFX will eventually overwrite them.

      The tricky part is how these properties work. They do not actually change layout pixel scaling, as you and I had expected. Instead, they only change rendering pixel scaling (as per their names). To see how this works, set the renderScales to something very low (like 0.5 or 0.1) and draw a simple shape like a circle in the window in question. You’ll see that the shape is still the same size in terms of layout pixels, but it is drawn with heavy aliasing, indicating that rendering was downscaled to a correspondingly coarser resolution.

      So unfortunately renderScale is not actually very useful to application developers. I assume it was introduced to help the JavaFX team tweak low-resolution rendering without having to switch the entire test application to the target resolution.

      Speaking of which, on Windows the mentioned startup switch works perfectly to set the actual output scaling for an entire application. Does this not work on Linux?

Leave a Reply