18

I have a Java Swing program that uses the System Look And Feel:

UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ());

The problem is that on a high-DPI system, the fonts in the frames are way too small. How can I make the text on my frames readable without having to change the fonts for ALL the frames? My program was written using Java 6 and has too many frames to modify.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user1828108
  • 447
  • 1
  • 4
  • 11

2 Answers2

15

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

HappyPig

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)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I think that this requires manual setting of a specific font size, which is not adaptable on different systems. And it does not change other graphic element sizes (icons...). – guthrie Jun 01 '17 at 08:51
  • @guthrie You'd have to consider a scaling factor based on the requirements and settings, but based on the question requirement, it's a start. I understand Java 9 was implementing "x" scaling of images, similar to what iOS does – MadProgrammer Jun 01 '17 at 08:57
  • In case one needs a scaling factor, I just made a class that should be very useful for manual scaling of components or custom graphics across Java 8 **and** 9. https://stackoverflow.com/a/46630710/3500521 It derives the system's GUI scaling factor, an independent such factor for custom graphics (because you don't need manual component scaling on Java 9 but maybe still manual scaling for custom graphics, depending on what you're doing), etc. – Dreamspace President Oct 08 '17 at 12:05
  • @MadProgrammer ok I mod flagged it for deletion I can't stand all this darn plagiarism stuff at least heck reference who came up with the code. – Petter Friberg Dec 01 '17 at 16:44
  • I love how people are willing to downvote an answer, without context or feedback or even providing a new answer - makes me wonder if they actually understand the question or solution – MadProgrammer Feb 26 '18 at 07:15
  • Great, this did 95% of what I needed. Only had to do call `table.setRowHeight(32);` for my JTable instances in addition to this (default is 16). – Jonas Berlin Aug 15 '18 at 10:49
  • I updated `setDefaultSize(int size)` to `scaleDefaultSize(double scale)` and changed the "deriveFont" line to `font = font.deriveFont(font.size * scale);` so all font sizes would be scaled up in same proportions instead of all set to the same size. – Jonas Berlin Aug 15 '18 at 10:52
  • Great answer for cases that only use message box to debug the application. – jw_ Sep 24 '19 at 02:46
6

I can't say for sure if this fully addresses the issue, but apparently high DPI Java is fixed for Mac in Java 7, and fixed for Linux and Windows in Java 9.

JEP 263: HiDPI Graphics on Windows and Linux: http://openjdk.java.net/jeps/263

corresponding ticket: https://bugs.openjdk.java.net/browse/JDK-8055212

Joshua Goldberg
  • 5,059
  • 2
  • 34
  • 39
  • 4
    Also the `GDK_SCALE` environment variable needs to be set to something larger than `1`. – dvim Jun 04 '18 at 16:27
  • 1
    We did not need to set GDK_SCALE in order to take advantage of the fixes when we updated a Swing application to Java 10. – Joshua Goldberg Jun 05 '18 at 12:35