Java/Scala: How to determine the monitor sizes of multiple displays

Note: This code is currently a work in progress. I try to demonstrate some possible approaches, but I don’t know of a perfect working solution yet.

I’m currently trying to find the right way to find the current monitor size, when you’re writing a Java Swing application to work in a multiple-monitor configuration. I always use three monitors, so I can test this pretty easily.

Java default screen device

This SO post says that this code works, but it doesn’t work for me on Mac OS X 10.10:

GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();

From what I can tell, the “default” screen device is not the same as the “current” screen device. For instance, my default screen device seems to be my display that’s in the middle of the three that I use, but that’s not the same as what I consider to be the “current” display, which to my way of thinking is the display where my JFrame is currently displayed.

Multiple screen devices

This second approach, which is based on an answer that’s shown lower on that page, does give me three different monitor sizes, so I hope the answer is in there somewhere:

private String getMonitorSizes() {        
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice[]    gs = ge.getScreenDevices();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < gs.length; i++) {
        DisplayMode dm = gs[i].getDisplayMode();
        sb.append(i + ", width: " + dm.getWidth() + ", height: " + dm.getHeight() + "\n");
    }    
    return sb.toString();
}

With two monitors connected to my MacBook, with the MacBook lid closed, I see this output from this method:

width = 1920, height = 1080
0, width: 1440, height: 900
1, width: 1920, height: 1080

If you’re trying to work with multiple monitors in a Java Swing or JavaFX application, I can’t tell you exactly how to determine the current monitor size, but as I mentioned, that last code does give different monitor sizes.

One-monitor screen resolution solution

FWIW, those approaches should work if you have only one monitor/display. This older approach should also work:

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();

A complete Java Swing test app

Also, here’s the source code for a complete Java application you can use to test the problem, and possibly find a solution:

package current_monitor_size;

import java.awt.DisplayMode;
import java.awt.FlowLayout;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class CurrentMonitorSize {

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

    public CurrentMonitorSize() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {

                final JFrame frame = new JFrame("Current Monitor Size");
                frame.setSize(600, 400);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT, 10, 5));

                final JTextField textField = new JTextField(20);
                final JButton updateButton = new JButton("Update");
               
                updateButton.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                      textField.setText(getWidthHeightString());
                      //textField.setText(getMonitorSizes());
                  }
                });
               
                frame.getContentPane().add(textField);
                frame.getContentPane().add(updateButton);

                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private String getWidthHeightString() {
        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        int width = gd.getDisplayMode().getWidth();
        int height = gd.getDisplayMode().getHeight();
        return "width = " + width + ", height = " + height;
    }
   
    private String getMonitorSizes() {       
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[]    gs = ge.getScreenDevices();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < gs.length; i++) {
            DisplayMode dm = gs[i].getDisplayMode();
            sb.append(i + ", width: " + dm.getWidth() + ", height: " + dm.getHeight() + "\n");
        }   
        return sb.toString();
    }

}

Finally, I guess I should say that the first approach may work on MS Windows, I don’t know, but as I mentioned, I can confirm that it doesn’t work on Mac OS X.