'False SWING Component Placement in Java with 4K Monitor

I have a component placement problem. First I'll try to give (possibly useful) information and then tell you about the main problem:

My System: Windows 8.1 64bit, Java 1.8.0_60 32bit

What I'm trying to do is: After I learn screen resolutions of all connected screens, I'm placing some swing components around the screen. This means that I need to know the resolutions of the screens.

I'm using multiple monitors.

  1. 3840 x 2160 (main monitor)

  2. 1920 x 1080 (secondary)

I use:

graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
devices = graphicsEnvironment.getScreenDevices();

And for the main screen device:

devices[i].getDefaultConfiguration().getBounds()

returns [0, 0, 2560, 1440]. Instead of the right values 3840 x 2160.

Interesting thing is;

devices[i].getDisplayMode().getWidth() and getHeight() 

returns the right 3840 and 2160 values.

Note: This difference does not happen in any other resolution selection of the screen. For example, if I select 1920 x 1080 for the main screen, both "getDefaultConfiguration().getBounds()" and "getDisplayMode().getWidth()" returns the right values.

Now,

You can say that I'm already getting the right dimensions. So, what is the matter?

The thing is, when I try to position my SWING components, they are placed in wrong positions. For example, an element at [3750, 0, 10, 10] ends up inside the second monitor, while It should have been on the right upper corner of the first screen.

Another example: As you know, a fixed sized component would appear smaller in higher resolutions. Since its pixel percentage related to screen gets smaller, the component itself also looks smaller. For example; When I increase my screen's resolution from 1920x1080 to 2560x1440, my components gets smaller. But, when I increase the resolution from 2560x1440 to 3840x2160; they stay in the same size.

I hope I was clear about the problem.



Solution 1:[1]

I know of one Windows 8+ specific feature, which might manifest in that way: per-display DPI setting. The feature is supposed to keep application window at the same size physically, even when dragging them across displays with different density.

This is achieved by rendering the application's window into a intermediate buffer, which then is scaled by the DWM taking the target screen DPI into account.

This feature can be disabled, using following dialog:

Compatibility settings

It has to be done on the file containing the executable program, which displays any frames. In Java, it's somewhat convoluted, since it's a hosting application. Changing this on java(w).exe should alter the behavior globally.

Typically, this kind of flag adjustment is done by a software installer. It's possible to wrap the java jar into a exe with a thin wrapper. I like launch4j the most for this task. The wrapper exe and the jar file can be wrapped into a installer script, which sets the flag at installation time.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1