I have the following code:
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
public class GraphicsEnvironmentTest {
public static void main(String[] args) {
GraphicsEnvironment localGraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice defaultScreenDevice = localGraphicsEnvironment.getDefaultScreenDevice();
GraphicsConfiguration defaultConfiguration = defaultScreenDevice.getDefaultConfiguration();
System.out.println("defaultConfiguration.getBounds() " + defaultConfiguration.getBounds());
System.out.println("defaultConfiguration.getDefaultTransform() " + defaultConfiguration.getDefaultTransform());
}
}
With Java 8 i get the following:
defaultConfiguration.getBounds() java.awt.Rectangle[x=0,y=0,width=2560,height=1600]
defaultConfiguration.getDefaultTransform() AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
With Java 17 i get the following:
defaultConfiguration.getBounds() java.awt.Rectangle[x=0,y=0,width=1707,height=1067]
defaultConfiguration.getDefaultTransform() AffineTransform[[1.5, 0.0, 0.0], [0.0, 1.5, 0.0]]
Why is this different? Is this a bug?
Here the exact java versions:
Java 8: 1.8.0_242
Java 17: Eclipse Adoptium - Temurin-17.0.7+7
You can only reproduce this, if you have a scaling different from 100% of your operating system. Go to system->screen setting.
5
I found a JVM parameter, which disable scaling. This fixes the problem:
-Dsun.java2d.uiScale.enabled=false
See also:
How to disable scaling the UI on Windows, for Java 9 applications?
I can reproduce the change you noticed if my screen display scaling is not 100%. At this point, the coordinates and scaling reported by JDK8 and JDK23 differ. As I have two screens, I use this test program:
GraphicsDevice[] screens = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
Arrays.stream(screens).map(GraphicsDevice::getDefaultConfiguration).forEach(device -> {
System.out.println("getBounds() " + device.getBounds());
System.out.println("getDefaultTransform() " + device.getDefaultTransform());
});
At 100% I see identity AffineTransform
on both JDK:
getBounds() java.awt.Rectangle[x=0,y=0,width=1920,height=1080]
getDefaultTransform() AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
getBounds() java.awt.Rectangle[x=-1680,y=32,width=1680,height=1050]
getDefaultTransform() AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
At 110% the bounds and AffineTransform
changed on newer JDK (1920 being ~ 1739 x 1.104166626930237):
getBounds() java.awt.Rectangle[x=0,y=0,width=1739,height=978]
getDefaultTransform() AffineTransform[[1.104166626930237, 0.0, 0.0], [0.0, 1.104166626930237, 0.0]]
getBounds() java.awt.Rectangle[x=-1680,y=32,width=1522,height=951]
getDefaultTransform() AffineTransform[[1.104166626930237, 0.0, 0.0], [0.0, 1.104166626930237, 0.0]]
Most likely, the reason for this difference will be explained by searching the JDK bug database and checking release version JDK9+. Two worth noting in particular:
- Window positioning bugs due to overlapping GraphicsDevice bounds (Windows/HiDPI) Fixed JDK16
- Bounds of GraphicsConfiguration are incorrect on scaled HDPI monitors in JDK16 Not an Issue
Reverting to 100% scale will ensure the JDKs report same values. If this applies to your case, it is JDK8 that is incorrect, and JDK17 is correct.
Note that you can access the scaled and unscaled getBounds
in later JDKs by reading DisplayMode
, so it might be possible to write same code for JDK8 and later JDKs if you can only depend on the “unscaled” version of the screen bounds rather than the scaled getBounds()
values:
Arrays.stream(screens).map(GraphicsDevice::getDefaultConfiguration)
.forEach(conf -> {
DisplayMode dm = conf.getDevice().getDisplayMode();
Rectangle bounds = conf.getBounds();
System.out.println(conf+".getBounds() " + bounds);
System.out.println(conf+" unscaled " + new Rectangle((int)bounds.getX(), (int)bounds.getY(), dm.getWidth(), dm.getHeight()));
});
// JDK23 output for "unscaled" matches JDK8:
getBounds() java.awt.Rectangle[x=0,y=0,width=1739,height=978]
unscaled java.awt.Rectangle[x=0,y=0,width=1920,height=1080]
getBounds() java.awt.Rectangle[x=-1680,y=32,width=1522,height=951]
unscaled java.awt.Rectangle[x=-1680,y=32,width=1680,height=1050]
2