最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swing - How to correct center window on a screen in Java 11 with Temurin VMOracle VM - Stack Overflow

programmeradmin0浏览0评论

I want to center my JFrame in a 4K Screen (3840x2400) with 250% scaling for Java 11. This screen is a secondary screen in Windows and placed left to the my main screen (Full HD, 1920x1080, 100% scaling). I have no another screens in my system.

I have following code to do it:

/**
 * Locates the given window at the center of its current graphics device.
 *
 * @param aWindow window to center.
 */
public static void center(Window aWindow) { // window was created with a correct GraphicsConfiguration
    final Dimension paneSize = aWindow.getSize();
    Rectangle screenBounds = aWindow.getGraphicsConfiguration().getBounds();
    subtractInsets(aWindow.getGraphicsConfiguration(), screenBounds);
    aWindow.setLocation(screenBounds.x + (screenBounds.width - paneSize.width) / 2,
            screenBounds.y + (screenBounds.height - paneSize.height) / 2);
}

private static void subtractInsets(GraphicsConfiguration display, Rectangle bounds) {
    Insets ins = Toolkit.getDefaultToolkit().getScreenInsets(display);
    bounds.x += ins.left;
    bounds.y += ins.top;
    bounds.width -= ins.left + ins.right;
    bounds.height -= ins.top + ins.bottom;
}

When I run this code on Open JDK (Temurin) this code works correctly. And when I print my screen bounds i get java.awt.Rectangle[x=-1536,y=0,width=1536,height=960]. But when I run it on Oracle JDK my window goes placed on both screens (ugly) and when I print my screen bounds i get java.awt.Rectangle[x=-3840,y=0,width=1536,height=960].

I've found a solution, that works for both cases. Here is it:

/**
 * Locates the given window at the center of its current graphics device.
 *
 * @param aWindow window to center.
 */
public static void center(Window aWindow) {
    final Dimension paneSize = aWindow.getSize();
    Rectangle screenBounds = aWindow.getGraphicsConfiguration().getBounds();
    updateBoundsForDisplayIfRequired(screenBounds, aWindow.getGraphicsConfiguration());
    subtractInsets(aWindow.getGraphicsConfiguration(), screenBounds);
    aWindow.setLocation(screenBounds.x + (screenBounds.width - paneSize.width) / 2,
            screenBounds.y + (screenBounds.height - paneSize.height) / 2);
}

private static void subtractInsets(GraphicsConfiguration display, Rectangle bounds) {
    Insets ins = Toolkit.getDefaultToolkit().getScreenInsets(display);
    bounds.x += ins.left;
    bounds.y += ins.top;
    bounds.width -= ins.left + ins.right;
    bounds.height -= ins.top + ins.bottom;
}

private static void updateBoundsForDisplayIfRequired(@Nonnull Rectangle bounds, @Nonnull GraphicsConfiguration display) {
    if (isOracleVM()) {
        bounds.x = (int) Math.round(bounds.x * display.getDefaultTransform().getScaleX());
        bounds.y = (int) Math.round(bounds.y * display.getDefaultTransform().getScaleY());
        bounds.width = (int) Math.round(bounds.width * display.getDefaultTransform().getScaleX());
        bounds.height = (int) Math.round(bounds.height * display.getDefaultTransform().getScaleY());
    }
}

/**
 * Checks whether we are in the Oracle VM. Some AWT features works different with Oracle vs. Open JDK.
 * 
 * @return true if we are in oracle VM.
 */
public static boolean isOracleVM() {
    return System.getProperty("java.vendor", "").contains("Oracle");
}

But I'm not sure whether it's a correct solution for all screen combinations and VMs. Can somebody verify/improve my code?

发布评论

评论列表(0)

  1. 暂无评论