How to set the DPI of Java Swing apps on Windows/Linux?


Answers

You can modify fonts like this

public class Test {

public static void main(String[] args) {
    new Test();
}

public Test() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            setDefaultSize(24);

            JFrame frame = new JFrame("Testing frame");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new JLabel("Hello world"));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}

public static void setDefaultSize(int size) {

    Set<Object> keySet = UIManager.getLookAndFeelDefaults().keySet();
    Object[] keys = keySet.toArray(new Object[keySet.size()]);

    for (Object key : keys) {

        if (key != null && key.toString().toLowerCase().contains("font")) {

            System.out.println(key);
            Font font = UIManager.getDefaults().getFont(key);
            if (font != null) {
                font = font.deriveFont((float)size);
                UIManager.put(key, font);
            }

        }

    }

}

}

use the same approach for increasing or decreasing fonts for different layouts

Question

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?




Use JRE 9 (or greater).

This is because the Java runtime (older versions) declared themselves 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.

Then, You need to run it on JRE 9 because it really supports this feature.




Java Swing on high-DPI screen

You could physically modify the look and feel's font settings...

import java.awt.EventQueue;
import java.awt.Font;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                setDefaultSize(24);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JLabel("Happy as a pig in a blanket"));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static void setDefaultSize(int size) {

        Set<Object> keySet = UIManager.getLookAndFeelDefaults().keySet();
        Object[] keys = keySet.toArray(new Object[keySet.size()]);

        for (Object key : keys) {

            if (key != null && key.toString().toLowerCase().contains("font")) {

                System.out.println(key);
                Font font = UIManager.getDefaults().getFont(key);
                if (font != null) {
                    font = font.deriveFont((float)size);
                    UIManager.put(key, font);
                }

            }

        }

    }

}

We use a similar approach to increase/decrease the font size of the running application to test layouts (and eventually allow the user some additional control over the font size)




Java / Swing how to deal with different screen DPI and density settings?

First, trust the platform's Look & Feel designers to choose sensible default sizes for text and controls. Then, avoid the temptation to frustrate those defaults. Here are some heuristics:

  • Use layouts; when contemplating absolute positioning, consider a custom layout.

  • Respect the preferred size of components.

  • Avoid non-resizable components.

  • In animation, scale graphics to the size of the enclosing Window.

  • Test across a range of platforms, using emulation as required.




So the actual answer seems to be: no you can't. That really is a bummer because it's a pain to test.