开发者

Java MouseEvent, check if pressed down

I have a class that implements MouseListener (JPanel). When I click on the panel something happens. What I want is some kind of while-loop that loops as long as left mousebutton is pressed down.

@Override
public void mousePressed(MouseEvent e) {
    while(e.isPressedDownD) {      // <--
        //DO SOMETHING
    }
}

This obviously doesn't work, but I hope you understand what I'm trying to achieve. The whole class for those that are interested:

package control;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import model.GridModel;
import view.GUIView;

public class MapListener implements MouseListener{
    private GridModel model;
    private GUIView view;
    private int 开发者_开发百科posX;
    private int posY;

    public MapListener(GridModel model, GUIView view) {
        this.model = model;
        this.view = view;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        posX = e.getX();
        posY = e.getY();
        model.setMouseAtX(posX);
        model.setMouseAtY(posY);
        view.paintTile();
        System.out.println("X: " + posX + " Y: " + posY);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent arg0) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        while(e.getModifiers() == MouseEvent.MOUSE_PRESSED) { //Obviously doesn't work
            //DO SOMETHING
        }
    }

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


As pointed out by other answers, the place to do your work is not in the mouse event listener methods.

Also there is no explicit "mouse pressed" notion in MouseEvent, so you must track that yourself. I have provided an example of how to do this. Also note the MouseEvent.BUTTON1 references, as this is just to track the state of the left mouse button.

This is where you must start to learn about concurrency. For that reason, I've added in a synchronized method as you need to be aware that funny things happen when multiple threads access properties at the same time, and synchronized is a mechanism for keeping this sane. Consider it further reading beyond the scope of this example.

Untested, but this should work:

volatile private boolean mouseDown = false;

public void mousePressed(MouseEvent e) {
    if (e.getButton() == MouseEvent.BUTTON1) {
        mouseDown = true;
        initThread();
    }
}

public void mouseReleased(MouseEvent e) {
    if (e.getButton() == MouseEvent.BUTTON1) {
        mouseDown = false;
    }
}

volatile private boolean isRunning = false;
private synchronized boolean checkAndMark() {
    if (isRunning) return false;
    isRunning = true;
    return true;
}
private void initThread() {
    if (checkAndMark()) {
        new Thread() {
            public void run() {
                do {
                    //do something
                } while (mouseDown);
                isRunning = false;
            }
        }.start();
    }
}


Why do so many of these answers wrongly assert that there is no explicit "mouse pressed" notion in MouseEvent?

Although the other commenters are correct that the OP should not be doing all that stuff in an event handler, there are other situations in which querying the button state in a mouse listener is useful. In those cases, you actually CAN determine the button down state. For example:

@Override
public void mouseExited(MouseEvent event) // Or any other mouse event handler...
{
    int buttonsDownMask = MouseEvent.BUTTON1_DOWN_MASK 
            | MouseEvent.BUTTON2_DOWN_MASK 
            | MouseEvent.BUTTON3_DOWN_MASK; // Or whichever buttons you care about...
    if ( (event.getModifiersEx() & buttonsDownMask) != 0 )
        System.out.println("Hey! Some button is pressed!");
}

Notice in particular the use of the MouseEvent.getModifiersEx() method, along with MouseEvent.BUTTON1_DOWN_MASK and friends.


You could create a new Thread containing your while loop. You start that Thread when the mouse button is pressed. You stop it when the mouse button is released.


You shouldn't be doing that in an event handler as no more events will be processed until the event handler exits.

What you want to achieve can be done with a separate worker thread. Create the thread from the mousePressed listener, do whatever you want to do in the thread (this should contain the while loop) and make the thread exit when the mouse is released (your mouseReleased listener should notify the thread).


for example

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

public class ClickListener extends MouseAdapter implements ActionListener {

    private final static int clickInterval = (Integer) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
    private MouseEvent lastEvent;
    private Timer timer;

    public ClickListener() {
        this(clickInterval);
    }

    public ClickListener(int delay) {
        timer = new Timer(delay, this);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        /*if (e.getClickCount() > 2) {
            return;
        }
        lastEvent = e;
        if (timer.isRunning()) {
            timer.stop();
            doubleClick(lastEvent);
        } else {
            timer.restart();
        }*/

        if (timer.isRunning() && !e.isConsumed() && e.getClickCount() > 1) {
            System.out.println("double");
            timer.stop();
        } else {
            timer.restart();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        timer.stop();
        singleClick(lastEvent);
    }

    public void singleClick(MouseEvent e) {
    }

    public void doubleClick(MouseEvent e) {
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Double Click Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addMouseListener(new ClickListener() {

            @Override
            public void singleClick(MouseEvent e) {
                System.out.println("single");
            }

            @Override
            public void doubleClick(MouseEvent e) {
                System.out.println("double");
            }
        });
        frame.setPreferredSize(new Dimension(200, 200));
        frame.pack();
        frame.setVisible(true);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜