Java 将JFrame捕捉到屏幕边缘

Java 将JFrame捕捉到屏幕边缘,java,swing,window,jframe,Java,Swing,Window,Jframe,我将以“这更像是一个答案”作为序言 我自己回答这个问题 我用标签搜索,我用谷歌搜索,我用标签和纯文本的组合搜索(在这个网站上),但我仍然找不到这个该死的问题。有人粘贴源代码或链接源代码作为答案 这是(其中一个)原始来源,它遍布网络 (code.google.com域,如有必要,我可以使用完整的URL进行编辑) 这并不完美。0的偏移量似乎并不总是有效(在我的家用机器上测试,在这里,使用多监视器设置,没有),而5的偏移量有效。它不支持多显示器。这种突然的行为有点容易激动(它会持续激发) 答案就是这个

我将以“这更像是一个答案”作为序言

我自己回答这个问题

我用标签搜索,我用谷歌搜索,我用标签和纯文本的组合搜索(在这个网站上),但我仍然找不到这个该死的问题。有人粘贴源代码或链接源代码作为答案

这是(其中一个)原始来源,它遍布网络

(code.google.com域,如有必要,我可以使用完整的URL进行编辑)

这并不完美。0的偏移量似乎并不总是有效(在我的家用机器上测试,在这里,使用多监视器设置,没有),而5的偏移量有效。它不支持多显示器。这种突然的行为有点容易激动(它会持续激发)


答案就是这个问题的答案。请随意锁定、归档等。只是想帮点忙:)

所以,看看改进后的代码。希望它能帮助人们,而且它不会太冗长,也不会让人读起来很痛苦

package widgets;

import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

public class WindowSnapper extends ComponentAdapter {

    private boolean locked = false;

    // feel free to modify; set based on my own preferences
    // incorporate as user option?
    private int sd = 30;
    private GraphicsDevice[] screenList  = GraphicsEnvironment
            .getLocalGraphicsEnvironment().getScreenDevices();  

    // clamping at 5 seems correct, 0 clamps at -5 beyond screen boundary
    public void componentMoved(ComponentEvent evt) {
        // gets current display device
        Window myWindow = new Window((Frame) evt.getComponent());
        GraphicsConfiguration config = myWindow.getGraphicsConfiguration();
        GraphicsDevice myScreen = config.getDevice();
        // matches against active display
        for(GraphicsDevice gd : getScreenList()) {
            // this will set the display to a new display if the window is moved to a new display
            if(gd.equals(myScreen)) {
                myScreen = gd;
                break;
            }
        }

        // minimising calls to stack
        int screenWidth = myScreen.getDefaultConfiguration().getBounds().width;
        int screenHeight = myScreen.getDefaultConfiguration().getBounds().height;
        int compWidth = evt.getComponent().getWidth();
        int compHeight = evt.getComponent().getHeight();
        int nx = evt.getComponent().getX();
        int ny = evt.getComponent().getY();
        // setting offsets in case of different screen
        int currentX = myScreen.getDefaultConfiguration().getBounds().x;
        int currentY = myScreen.getDefaultConfiguration().getBounds().y;

        // see end of method
        // OR conditions seem to stabilise movement when close to screen edge
        if(locked
                || nx == currentX + 5
                || ny == currentY + 5
                || nx == currentX + screenWidth - compWidth - 5
                || ny == currentY + screenHeight - compHeight - 5)
            return;

        // left
        if(nx < (currentX + sd) && nx > (currentX + 5)) {
            nx = currentX + 5;
        }

        // top
        if(ny < (currentY + sd) && ny > (currentY + 5)) {
            ny = currentY + 5;
        }

        // right
        if(nx > currentX + screenWidth - compWidth - sd
                && nx < currentX + screenWidth - compWidth - 5) {
            nx = currentX + screenWidth - compWidth - 5;
        }

        // bottom
        if(ny > currentY + screenHeight - compHeight - sd
                && ny < currentY + screenHeight - compHeight - 5) {
            ny = currentY + screenHeight - compHeight - 5;
        }

        // make sure we don't get into a recursive loop when the
        // set location generates more events
        locked = true;
        evt.getComponent().setLocation(nx, ny);
        locked = false;
    }

    public int returnSD() {
        return sd;
    }

    public void setSD(int sd) {
        this.sd = sd;
    }

    public GraphicsDevice[] getScreenList() {
        return screenList;
    }

    public void setScreenList(GraphicsDevice[] screenList) {
        this.screenList = screenList;
    }

}
packagewidgets;
导入java.awt.Frame;
导入java.awt.GraphicsConfiguration;
导入java.awt.GraphicsDevice;
导入java.awt.GraphicsEnvironment;
导入java.awt.Window;
导入java.awt.event.ComponentAdapter;
导入java.awt.event.ComponentEvent;
公共类WindowSnapper扩展ComponentAdapter{
private boolean locked=false;
//随意修改;根据我自己的喜好设置
//合并为用户选项?
私人机构内部评级标准差=30;
专用图形设备[]屏幕列表=图形环境
.getLocalGraphicsEnvironment().getScreenDevices();
//在5处夹紧似乎正确,0在屏幕边界外-5处夹紧
公共无效组件已移动(组件事件evt){
//获取当前显示设备
Window myWindow=新窗口((Frame)evt.getComponent());
GraphicsConfiguration config=myWindow.getGraphicsConfiguration();
GraphicsDevice myScreen=config.getDevice();
//与活动显示的匹配
对于(GraphicsDevice gd:getScreenList()){
//如果将窗口移动到新显示器,则会将显示器设置为新显示器
if(gd.equals(myScreen)){
myScreen=gd;
打破
}
}
//最小化对堆栈的调用
int screenWidth=myScreen.getDefaultConfiguration().getBounds().width;
int screenHeight=myScreen.getDefaultConfiguration().getBounds().height;
int compWidth=evt.getComponent().getWidth();
int compHeight=evt.getComponent().getHeight();
int nx=evt.getComponent().getX();
int ny=evt.getComponent().getY();
//设置不同屏幕情况下的偏移量
int currentX=myScreen.getDefaultConfiguration().getBounds().x;
int currentY=myScreen.getDefaultConfiguration().getBounds().y;
//参见方法末尾
//或者,当靠近屏幕边缘时,条件似乎会稳定移动
如果(已锁定)
||nx==当前x+5
||ny==当前Y+5
||nx==当前x+屏幕宽度-compWidth-5
||ny==当前Y+屏幕高度-组件高度-5)
返回;
//左
如果(nx<(当前x+sd)和&nx>(当前x+5)){
nx=电流x+5;
}
//顶
如果(ny<(当前Y+sd)和&ny>(当前Y+5)){
ny=电流Y+5;
}
//对
如果(nx>currentX+screenWidth-compWidth-sd
&&nx当前Y+屏幕高度-组件高度-sd
&&ny<当前Y+屏幕高度-组件高度-5){
ny=当前Y+屏幕高度-组件高度-5;
}
//确保当
//设置位置会生成更多事件
锁定=真;
evt.getComponent().setLocation(nx,ny);
锁定=错误;
}
public int returnSD(){
返回sd;
}
公共空间设置D(内部sd){
这个.sd=sd;
}
公共图形设备[]获取屏幕列表(){
返回屏幕列表;
}
公共无效设置屏幕列表(图形设备[]屏幕列表){
this.screenList=屏幕列表;
}
}

它确实会咬合,但存在一些问题。当窗户装饰有阴影时,它在Windows 10上不起作用。阴影被捕捉到屏幕边缘,并且在窗口的真实边界和屏幕边缘之间始终存在一个空间。此外,当调整帧大小时,例如通过拖动左边框,捕捉会导致右边框移动。抓拍应该只吸引左边框,保持右边框不变。嗨@EmmanuelBourg,我已经有几年没看这个了,但我把它转回来做测试。看起来Windows或Java在某个时候已经更新了行为-我认为不再需要这个适配器了。我用一个没有添加这个的JFrame获得了更好的结果。感谢凹凸:)阴影问题可以通过从帧边界减去左/下/右插入(而不是顶部)来解决。