How to move maximized window

I wanted to write JFrame that maximizes only horizontally, and move it up and down by using mouse drag.

Here is the initial version.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class MaxMove1 extends JFrame 
    implements WindowListener, WindowStateListener,
           MouseListener, MouseMotionListener
{
    static final int W = 200;
    static final int H = 100;

    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    private Point startPoint;

    // WindowListener.
    public void windowClosing(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    // MouseListener.
    public void mousePressed(MouseEvent me) {
    startPoint = me.getPoint();
    }
    public void mouseReleased(MouseEvent me) {}
    public void mouseDragged(MouseEvent me) {
    Point loc = getLocation();
    int xx = loc.x + me.getX() - startPoint.x;
    int yy = loc.y + me.getY() - startPoint.y;
    if (getExtendedState() != NORMAL) xx = 0;
    setLocation(xx, yy);
    setMaximizedBounds(new Rectangle(0, yy, screen.width, H));
    }
    public void mouseMoved(MouseEvent me) {}
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}

    // Appearance.
    class MyCanvas extends JComponent {
    public void paint(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
    }

    // Main program.
    public MaxMove1(){
    JComponent canvas = new MyCanvas();
    canvas.setVisible(true);
    add(canvas);

    addWindowListener(this);
    addWindowStateListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setSize(W, H);
    setMaximizedBounds(new Rectangle(0, 0, screen.width, H));
    setUndecorated(true);
    setVisible(true);
    }

    public static void main(String[] args) {
    new MaxMove1();
    }
}import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class MaxMove1 extends JFrame 
    implements WindowListener, WindowStateListener,
           MouseListener, MouseMotionListener
{
    static final int W = 200;
    static final int H = 100;

    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    private Point startPoint;

    // WindowListener.
    public void windowClosing(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    // MouseListener.
    public void mousePressed(MouseEvent me) {
    startPoint = me.getPoint();
    }
    public void mouseReleased(MouseEvent me) {}
    public void mouseDragged(MouseEvent me) {
    Point loc = getLocation();
    int xx = loc.x + me.getX() - startPoint.x;
    int yy = loc.y + me.getY() - startPoint.y;
    if (getExtendedState() != NORMAL) xx = 0;
    setLocation(xx, yy);
    setMaximizedBounds(new Rectangle(0, yy, screen.width, H));
    }
    public void mouseMoved(MouseEvent me) {}
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}

    // Appearance.
    class MyCanvas extends JComponent {
    public void paint(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
    }

    // Main program.
    public MaxMove1(){
    JComponent canvas = new MyCanvas();
    canvas.setVisible(true);
    add(canvas);

    addWindowListener(this);
    addWindowStateListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setSize(W, H);
    setMaximizedBounds(new Rectangle(0, 0, screen.width, H));
    setUndecorated(true);
    setVisible(true);
    }

    public static void main(String[] args) {
    new MaxMove1();
    }
}

Try this:
– Drag by mouse.
– Maximize by using task bar menu.
– Restore by using task bar menu.
– Maximize again by using task bar menu.
– Drag by mouse. Nicely goes up and down.
– Restore by using task bar menu. (Oops.)

The problem is setLocation(). By doing this Windows is told that the Frame is not maximized any more. But Java still thinks it is maximized. Probably I went into a glitch on the spec or imprementation.

So I should avoid setLocation() when Frame is maximized, and I am probably supposed to use setMaximizedBounds() to tell where the Frame should go. setMaximizedBounds() doesn’t move Frame until the Frame is maximized again. I don’t want to perform Restore/Maximize combo because it may show a flicker.

So I decided as follows:

– Use setLocation() even if maximized.
– Remember the maximized state when I start dragging.
– Keep the non-maximized location in Frame.
– When the mouse is released, I restore the condition.
– When the Frame is un-maximized, I restore the condition.

Here is the final version:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class MaxMove2 extends JFrame 
    implements WindowListener, WindowStateListener,
           MouseListener, MouseMotionListener
{
    static final int W = 200;
    static final int H = 100;

    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    private Point startPoint;
    private boolean startMaximized;
    private boolean dragged = false;
    private int x = 0;
    private int y = 0;
    private int w = W;
    private int h = H;

    // WindowListener.
    public void windowClosing(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {
    if (e.getNewState() == NORMAL) {
        setLocation(x, y);
        setSize(w, h);
    }
    }
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    // MouseListener.
    public void mousePressed(MouseEvent me) {
    startPoint = me.getPoint();
    startMaximized = (getExtendedState() != NORMAL);
    }
    public void mouseReleased(MouseEvent me) {
    if (startMaximized && dragged) {
        setExtendedState(NORMAL);
        setExtendedState(MAXIMIZED_BOTH);
    }
    dragged = false;
    }
    public void mouseDragged(MouseEvent me) {
    Point loc = getLocation();
    int xx = loc.x + me.getX() - startPoint.x;
    int yy = loc.y + me.getY() - startPoint.y;
    setLocation((getExtendedState() == NORMAL)? xx : 0, yy);
    setMaximizedBounds(new Rectangle(0, yy, screen.width, H));

    if (! startMaximized) x = xx;
    y = yy;
    dragged = true;
    }
    public void mouseMoved(MouseEvent me) {}
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}

    // Appearance.
    class MyCanvas extends JComponent {
    public void paint(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
    }

    // Main program.
    public MaxMove2(){
    JComponent canvas = new MyCanvas();
    canvas.setVisible(true);
    add(canvas);

    addWindowListener(this);
    addWindowStateListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setLocation(x, y);
    setSize(w, h);
    setMaximizedBounds(new Rectangle(0, 0, screen.width, H));
    setUndecorated(true);
    setVisible(true);
    }

    public static void main(String[] args) {
    new MaxMove2();
    }
}

I had to do Restore/Maximize combo when the Frame is un-maximized. But it doesn’t cause flicker because the window is same as maximized size before the operation.

This is always the way when I program in Java: I find shortcomings or glitches in the spec or implementation, then I have to move the wrinkle caused by the glitch around to fit some place where it doesn’t matter.

Advertisements