首页 > 解决方案 > 使用具有不同比例设置的多个显示器时,AWT GraphicsConfig 存在坐标问题

问题描述

我正在开发一个使用 JavaFx 并使用 SwingNode 嵌入一些 java AWT/Swing 组件的应用程序。最近,我注意到在每个显示器上使用具有不同缩放比例的多显示器设置时出现了一些奇怪的行为。新打开的弹出窗口(即上下文菜单和组合框内容弹出窗口)放错了位置。

主屏幕定义坐标系,左侧的另一个显示获得负坐标。(见下图)

https://i.stack.imgur.com/FIu4R.png

显示器 1 的左上角坐标应该与显示器 2 的右上角坐标相同。但事实并非如此。

AWT 的 [-1536,771] 与 [-1920,964] 和 javafx 的 [-1920,443] 与 [-1920,443]

我们将问题追溯到 awt-Win32GraphicsConfig getBounds 方法。据我了解,屏幕 1(左显示)的缩放是根据 x/y 的绝对值完成的。这导致假设下一个屏幕正在使用相同的缩放比例。

左上 x 值:-3840(平台 x)/1.25(缩放因子)= -3072

有了这个 x 值和 1536 的宽度,我们最终进入了显示 2 [-1920 到 0] 的坐标系

/*
 * Class:     sun_awt_Win32GraphicsConfig
 * Method:    getBounds
 * Signature: ()Ljava/awt/Rectangle
 */
JNIEXPORT jobject JNICALL
    Java_sun_awt_Win32GraphicsConfig_getBounds(JNIEnv *env, jobject thisobj,
                                               jint screen)
{
    jclass clazz;
    jmethodID mid;
    jobject bounds = NULL;

    clazz = env->FindClass("java/awt/Rectangle");
    CHECK_NULL_RETURN(clazz, NULL);
    mid = env->GetMethodID(clazz, "<init>", "(IIII)V");
    if (mid != 0) {
        RECT rRW = {0, 0, 0, 0};
        Devices::InstanceAccess devices;
        AwtWin32GraphicsDevice *device = devices->GetDevice(screen);

        if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) {

            int x = (device == NULL) ? rRW.left : device->ScaleDownX(rRW.left);
            int y = (device == NULL) ? rRW.top  : device->ScaleDownY(rRW.top);
            int w = (device == NULL) ? rRW.right - rRW.left
                                     : device->ScaleDownX(rRW.right - rRW.left);
            int h = (device == NULL) ? rRW.bottom - rRW.top
                                     : device->ScaleDownY(rRW.bottom - rRW.top);

            bounds = env->NewObject(clazz, mid, x, y, w, h);

        }
        else {
            // 4910760 - don't return a null bounds, return the bounds of the
            // primary screen
            int w = ::GetSystemMetrics(SM_CXSCREEN);
            int h = ::GetSystemMetrics(SM_CYSCREEN);

            bounds = env->NewObject(clazz, mid,
                                    0, 0,
                                    device == NULL ? w : device->ScaleDownX(w),
                                    device == NULL ? h : device->ScaleDownY(h));
        }
        if (safe_ExceptionOccurred(env)) {
           return 0;
        }
    }
    return bounds;
}

有什么想法可以解决这个问题吗?

标签: javaswingjavafxawt

解决方案


推荐阅读