GuiRitter
GuiRitter

Reputation: 757

Know if the mouse was clicked without a Listener, or a different approach

I'm working on making a undecorated JFrame, so I need a way to change the window position. So far, I can make the window follow the mouse, but I can't make it stop. I added an ActionPerformed to a JButton:

test = true;
while (test) {
    setLocation(MouseInfo.getPointerInfo().getLocation().x - 20, MouseInfo.getPointerInfo().getLocation().y - 20);
}

The offsets are there to keep the pointer inside the JButton, which graphically looks pressed during the while. It works wonders, very fast. But I don't know how to make it stop. I tried to add a MouseClicked that sets test to false, but it didn't worked. Apparently, no Listener works while the loop is running.

Is there a way to know if the mouse was clicked inside of that while? So, without a Listener or Event? Or is there another approach to re-position the window?

Edit:

Thanks again to Jurgen Camilleri, but I'd like to add a modified version of his example, which I believe is simpler, containing the barely necessary stuff to make this work.

package testbench;

import java.awt.EventQueue;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class DraggableFrame
 extends JFrame
 implements MouseListener, MouseMotionListener {

    static Point dragged = null;
    static Point pressed = null;

    public DraggableFrame () throws HeadlessException {
        addMouseListener(this);
        addMouseMotionListener(this);
        setBounds(0, 0, 320, 240);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setUndecorated(true);
    }

    public static void main (String args[]) {        
        EventQueue.invokeLater(new Runnable () {
            @Override
            public void run () {
                new DraggableFrame().setVisible(true);
            }
        });
    }

    @Override
    public void mouseClicked (MouseEvent e) {}

    @Override
    public void mouseDragged (MouseEvent e) {
        dragged = e.getLocationOnScreen();
        setLocation(
         (int)(dragged.getX() - pressed.getX()),
         (int)(dragged.getY() - pressed.getY()));
    }

    @Override
    public void mouseEntered (MouseEvent e) {}

    @Override
    public void mouseExited (MouseEvent e) {}

    @Override
    public void mouseMoved (MouseEvent e) {}

    @Override
    public void mousePressed (MouseEvent e) {
        pressed = e.getPoint();
    }

    @Override
    public void mouseReleased (MouseEvent e) {}
}

Don't mind the empty overridden methods, they are necessary. In the actual program I was developing, I used a separate class for the listeners, which works just as well. Also, it seems to not matter whether you implement a Listener or extend an Adapter. On one side, you can implement both interfaces. On the other side, you don't need to override all of the methods of the extended abstract class.

Also, this method works if you add the listeners to a container of your frame. However, it will behave as if that container is located at (0, 0). You'll have to add some offsets on setLocation().

Upvotes: 2

Views: 435

Answers (2)

Jurgen Camilleri
Jurgen Camilleri

Reputation: 3589

Try this:

public class UndecoratedJFrame extends JFrame {

    Point origin;
    Point origin2;

    public UndecoratedJFrame() {
        setUndecorated(true);
        initComponents();

        setVisible(true);
    }

    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                formMousePressed(evt);
            }
        });

        addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                formMouseDragged(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 400, Short.MAX_VALUE)
        );

        layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }                      

    private void formMouseDragged(java.awt.event.MouseEvent evt) {                                  
        origin2 = new Point(evt.getLocationOnScreen());
        setLocation((int)(origin2.getX() - origin.getX()), (int)(origin2.getY() - origin.getY()));
    }                                 

    private void formMousePressed(java.awt.event.MouseEvent evt) {                                  
       origin = new Point(evt.getPoint());
    }
}

Upvotes: 1

camickr
camickr

Reputation: 324108

so I need a way to change the window position.

For a different approach check out Moving Windows.

Upvotes: 2

Related Questions