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
相关产品推荐
相关产品推荐

