Java MouseEvent, проверьте, нажата ли - PullRequest
6 голосов
/ 26 июля 2011

У меня есть класс, который реализует MouseListener (JPanel). Когда я нажимаю на панель, что-то происходит. То, что я хочу, это какой-то цикл while, который повторяется до тех пор, пока нажата левая кнопка мыши.

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

Это, очевидно, не работает, но я надеюсь, что вы понимаете, чего я пытаюсь достичь. Весь класс для тех, кто заинтересован:

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) {
    }
}

Ответы [ 5 ]

15 голосов
/ 26 июля 2011

Как указывают другие ответы, место для выполнения вашей работы - , а не в методах прослушивания событий мыши.

Также в MouseEvent нет явного понятия «нажатие мышью», поэтому вы должны отслеживать это самостоятельно. Я привел пример того, как это сделать. Также обратите внимание на ссылки MouseEvent.BUTTON1, так как это просто для отслеживания состояния левой кнопки мыши.

Здесь вы должны начать изучать параллелизм. По этой причине я добавил синхронизированный метод, поскольку вам нужно знать, что забавные вещи случаются, когда несколько потоков обращаются к свойствам одновременно, и synchronized - это механизм для сохранения этого вменяемого. Считайте это более подробным чтением, выходящим за рамки этого примера.

Не проверено, но это должно работать:

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();
    }
}
10 голосов
/ 18 июля 2014

Почему многие из этих ответов ошибочно утверждают, что в MouseEvent нет явного понятия «нажатие мышью»?

Хотя другие комментаторы правы, что OP не должен делать все эти вещи в событииОбработчик, есть другие ситуации, в которых полезно запрашивать состояние кнопки в слушателе мыши.В этих случаях вы МОЖЕТЕ определить состояние нажатия кнопки.Например:

@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!");
}

Обратите особое внимание на использование метода MouseEvent.getModifiersEx() вместе с MouseEvent.BUTTON1_DOWN_MASK и друзьями.

4 голосов
/ 26 июля 2011

Вы можете создать новый поток, содержащий ваш цикл while.Вы запускаете эту тему, когда нажата кнопка мыши.Вы останавливаете его, когда кнопка мыши отпущена.

3 голосов
/ 26 июля 2011

Вы не должны делать это в обработчике событий, так как события не будут обрабатываться до тех пор, пока обработчик событий не выйдет.

То, чего вы хотите достичь, можно сделать с помощью отдельного рабочего потока.Создайте поток из прослушивателя mousePressed, сделайте все, что вы хотите сделать в потоке (он должен содержать цикл while), и сделайте выход из потока при отпускании мыши (ваш mouseReleased слушатель должен уведомить об этом поток).

2 голосов
/ 26 июля 2011

например

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