【问题标题】:Snapping JFrame to screen edge将 JFrame 捕捉到屏幕边缘
【发布时间】:2014-02-09 13:00:31
【问题描述】:

我将用“这更像是一个答案”作为开头。

如题,我自己来回答。

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

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

http://bit.ly/1eYKNXS(code.google.com 域,如有必要,我可以使用完整 URL 进行编辑)

这并不完美。偏移量 0 似乎并不总是有效(在我的家用机器和此处测试,使用多显示器设置和不使用),而偏移量 5 则有效。它不支持多显示器。快照行为有点令人兴奋(它一直在发射)。

答案就是这个问题的答案。随意锁定,存档等。只是想提供帮助:)

【问题讨论】:

    标签: java swing window jframe


    【解决方案1】:

    所以,看哪,改进的代码。希望它对人们有所帮助,并且它不会太冗长或阅读起来很痛苦。

    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;
        }
    
    }
    

    【讨论】:

    • 它确实很快,但有一些问题。当窗户装饰有阴影时,它在 Windows 10 上效果不佳。阴影捕捉到屏幕边缘,并且在窗口的实际边框和屏幕边缘之间始终存在空间。此外,当调整框架的大小时,例如通过拖动左边框,对齐会导致右边框移动。捕捉应该只吸引左边框而保持右边框不变。
    • 嗨@EmmanuelBourg,我已经好几年没看过这个了,但我把它转回来进行测试。看起来 Windows 或 Java 在某些时候已经更新了行为 - 我认为这个适配器不再是必需的。使用没有添加此功能的 JFrame 时,我得到了更好的结果。谢谢你的碰撞:)
    • 阴影的问题可以通过从框架的边界中减去左/下/右插图(不是顶部)来解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多