You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWT TrayIcon的MouseListener获取鼠标位置超出屏幕边界如何解决

问题根源

AWT的TrayIcon组件鼠标事件返回的坐标是物理像素坐标,而Toolkit.getDefaultToolkit().getScreenSize()获取的是适配系统缩放后的逻辑像素尺寸,系统缩放比例大于100%时就会出现物理坐标大于逻辑屏幕尺寸的问题。

解决方案

方案1:直接使用MouseInfo获取正确坐标(推荐)

鼠标点击事件触发时,直接调用MouseInfo.getPointerInfo().getLocation()获取坐标,该方法返回的是适配系统缩放后的逻辑坐标,无需额外换算,跨平台兼容性好。
修改后的mouseClicked方法示例:

@Override
public void mouseClicked(MouseEvent e) {
    // 直接获取适配系统缩放后的正确逻辑坐标
    Point correctPoint = MouseInfo.getPointerInfo().getLocation();
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

    System.out.println("Screen Size is x " + screenSize.getWidth() + " y " + screenSize.getHeight());
    System.out.println("Mouse clicked at x " + correctPoint.x + " y " + correctPoint.y);
    // 后续使用correctPoint的坐标放置窗口即可
}

方案2:手动获取系统缩放比例换算坐标

如果需要自行控制换算逻辑,可以先获取当前屏幕的缩放比例,再将物理坐标除以缩放比例得到逻辑坐标。

步骤1:编写获取缩放比例的工具方法

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;

// 获取水平方向缩放比例
private static double getScaleX() {
    // Java 9及以上版本直接通过GraphicsConfiguration获取
    if (Runtime.version().feature() >= 9) {
        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
                .getDefaultScreenDevice()
                .getDefaultConfiguration();
        return gc.getDefaultTransform().getScaleX();
    } else {
        // Java 8兼容方案,通过DPI计算缩放比例,默认96DPI为100%缩放
        return Toolkit.getDefaultToolkit().getScreenResolution() / 96.0;
    }
}

// 获取垂直方向缩放比例,大部分场景和水平比例一致
private static double getScaleY() {
    if (Runtime.version().feature() >= 9) {
        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
                .getDefaultScreenDevice()
                .getDefaultConfiguration();
        return gc.getDefaultTransform().getScaleY();
    } else {
        return Toolkit.getDefaultToolkit().getScreenResolution() / 96.0;
    }
}

步骤2:换算坐标

@Override
public void mouseClicked(MouseEvent e) {
    double scaleX = getScaleX();
    double scaleY = getScaleY();
    // 物理坐标除以缩放比例得到正确逻辑坐标
    int correctX = (int) (e.getXOnScreen() / scaleX);
    int correctY = (int) (e.getYOnScreen() / scaleY);
    // 后续使用correctX、correctY放置窗口即可
}

注意事项

  • 多显示器场景下,需要获取鼠标当前所在显示器的缩放比例进行换算,避免跨屏时坐标计算错误。
  • 窗口放置时需要额外判断任务栏位置,避免窗口被任务栏遮挡。

内容的提问来源于stack exchange,提问作者srilakshmikanthanp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:18:01