views:

616

answers:

4

In Windows 7, if you change the font size via the Control Panel->Appearance and Personalization -> Display "Make text and other items larger or smaller", it adjusts not only the menu sizes, but also the text content size of apps like Notepad, Wordpad, Firefox.

Is there a way to get Java to automatically scale the font without having to manually scale it?

A: 

This would depend entirely on what GUI toolkit you're using. I'm almost certain that SWT for instance would automatically pick up the new sizes (since it uses native widgets). AWT might as well for all I know. Can you specify what what toolkit you're using and whether you've determined that its not already doing what you want (and possibly how)?

Jherico
A: 
AFAIK, in Swing it's not possible. You may need to use JNI to achieve this.
Suraj Chandran
A: 

Thanks Suraj. I am using Swing, and have not been able to find a way to do it. I will look into using windows calls to get the information.

Glenn
+1  A: 

There are two parts to this:

  1. Getting your components, fonts, etc to scale
  2. Getting your layouts to scale

For Swing, the first part is easy - it all starts with one call.

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

On Windows, this will cause it to respect your Small/Large fonts (DPI) setting.

Here are two screenshots from a quick test app I threw together, demonstrating how it looks on my machine in Windows 7 @ 96dpi (normal font size) and @ 144dpi (150%)

First the default font size sample:

Swing app with Windows using normal font sizes

Now with Larger (150%) font size set:

Swing app with Windows using Larger font sizes

There is no code change between runs, only logging out & back in with new DPI settings. I set a fixed frame size on purpose to demonstrate that my containeris not scaling in size, so my label got pushed down in order to fit.

Here is my source code - cut & paste and run it yourself:

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class SwingFontTest
{
    private static void createGUI()
    {
        JButton button = new JButton("my button with Some Text");
        JLabel label = new JLabel("and a label");

        JPanel panel = new JPanel(new FlowLayout());
        panel.add(button);
        panel.add(label);

        JFrame frame = new JFrame("Title!");
        frame.setContentPane(panel);
        frame.setSize(300,125);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run()
            {
                createGUI();
            }
        });
    }

}

The Look & Feel supplies the default sizing, but it is up to the GUI author to use scalable units in their layouts. It does take effort (scalable layouts are a pain on webpages too!), but it's definitely attainable.

I recommend using a layout like FormLayout that will let you define your layouts in Dialog Units (DLU), as these scale with DPI. That will enable you to make your containers scale in size and should help limit behaviors like the label moving to the next line due to sizing. If the size of the frame was determined using dialog units then it could be made to look the same, only larger.

It is late - so that's it for now.

Joshua McKinnon