Search code examples
javaswingjframelistenerwindowstate

Listener that has events for when a frame is snapped to the left or right of screen


I know WindowStateListener will tell me if a component is maximized vertically, horizontally, or both. At least, it says it will. I do not know how to maximize a window exclusively horizontally or exclusively vertically outside of snapping the window to the left edge or right edge of my screen. Is there another listener for this behavior? Or will I need to make something myself that tracks mouse location in relation to the screen? I made an example program that displays what I've described.

SSCCE

import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
    SnapFrame frame = new SnapFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(new Dimension(500,500));
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    }
}
class SnapFrame extends JFrame implements WindowStateListener{
    public SnapFrame(){
        super();
        addWindowStateListener(this);
    }


@Override
public void windowStateChanged(WindowEvent arg0) {
     //will print a statement for all state change events except snapping to left/right edges of screen
    System.out.println("state changed");
}
}

If I wanted to have things triggered by this behavior, and there are no other listeners that have events for this, would a decent idea be to get my screen size and watch my mouse location for when it comes near the edge of my screen?


Solution

  • This source detects when the frame is snapped to the top or bottom of screen, using a ComponentListener. I don't know how to configure my Windows to snap to the left or right.

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.JFrame;
    
    public class Main {
    
        public static void main(String[] args) {
            SnapFrame frame = new SnapFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(new Dimension(500, 500));
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    }
    
    class SnapFrame extends JFrame implements ComponentListener {
    
        Dimension screenSize;
    
        public SnapFrame() {
            super();
            screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            addComponentListener(this);
        }
    
        @Override
        public void componentResized(ComponentEvent e) {
            Rectangle r = getBounds();
    
            if (r.getMinY()==0  || r.getMaxY()==(int)screenSize.getHeight()) {
                System.out.print("Well snap!");
            }
        }
    
        @Override
        public void componentMoved(ComponentEvent ignore) {}
    
        @Override
        public void componentShown(ComponentEvent ignore) {}
    
        @Override
        public void componentHidden(ComponentEvent ignore) {}
    }
    

    Other tips

    • Don't extend frame or other top level containers. Instead create & use an instance of one.
    • Swing GUIs should be created and updated on the EDT. See Concurrency in Swing for more details.