Java AWT:JFrame调用setLocation移动窗口时如何避免超出屏幕边界
问题原因
1. 边界判断逻辑错误
当前边界校验没有把窗口自身的宽高计算在内,向东移动时仅判断窗口左上角X坐标是否大于等于屏幕宽度就拦截,此时窗口右半部分已经完全超出屏幕;向南移动同理没有减去窗口高度。同时你用了else if串联所有判断,导致单次移动中X和Y的边界校验只能触发一个,两个方向同时超界时只会修复其中一个。
2. getEffectiveScreenArea实现错误
你当前在用的多屏幕计算逻辑不符合需求:
- 把所有屏幕的总宽高除以屏幕数,得到的不是当前窗口所在屏幕的可用区域
- 返回的Rectangle的width/height是区域尺寸,不是最大允许的坐标值
你注释掉的单屏幕版本逻辑更合理,但存在计算错误:effectiveScreenArea.height = bounds.height + screenInsets.top - screenInsets.bottom这里多了个+ screenInsets.top,导致可用高度计算错误。
修正方案
第一步:替换为正确的可用屏幕区域计算方法
修正你注释的单屏幕版本的计算错误即可,自动适配系统任务栏/停靠栏的遮挡:
private Rectangle getEffectiveScreenArea() { GraphicsConfiguration graphicsConfiguration = getGraphicsConfiguration(); Rectangle bounds = graphicsConfiguration.getBounds(); Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration); Rectangle effectiveScreenArea = new Rectangle(); effectiveScreenArea.x = bounds.x + screenInsets.left; effectiveScreenArea.y = bounds.y + screenInsets.top; // 修正高度计算错误 effectiveScreenArea.height = bounds.height - screenInsets.top - screenInsets.bottom; effectiveScreenArea.width = bounds.width - screenInsets.left - screenInsets.right; return effectiveScreenArea; }
第二步:修正refreshWindow的边界校验逻辑
拆分X、Y的判断逻辑,计算最大允许坐标时减去窗口自身的宽高,同时移除不必要的pack()调用:
private void refreshWindow() { Point lastLocation = getLocation(); Dimension windowSize = getSize(); // 获取当前窗口宽高 Rectangle effectiveScreenArea = getEffectiveScreenArea(); int newX = lastLocation.x + x; int newY = lastLocation.y + y; // 单独校验X轴边界 if (newX < effectiveScreenArea.x) { newX = effectiveScreenArea.x; } else if (newX + windowSize.width > effectiveScreenArea.x + effectiveScreenArea.width) { // 左上角X + 窗口宽度 不能超过 屏幕可用区域的最右坐标 newX = effectiveScreenArea.x + effectiveScreenArea.width - windowSize.width; } // 单独校验Y轴边界 if (newY < effectiveScreenArea.y) { newY = effectiveScreenArea.y; } else if (newY + windowSize.height > effectiveScreenArea.y + effectiveScreenArea.height) { // 左上角Y + 窗口高度 不能超过 屏幕可用区域的最下坐标 newY = effectiveScreenArea.y + effectiveScreenArea.height - windowSize.height; } setLocation(newX, newY); this.resetHeightAndWitdhLocally(); }
内容的提问来源于stack exchange,提问作者Jerome Wolff
相关产品推荐
相关产品推荐

