MouseListener для JPanel отсутствует событие mouseClicked

У меня есть JPanel, для которого я создал MouseListener, и я вижу какое-то поведение, которое не могу объяснить.

Обычно, когда я щелкаю мышью в JPanel, я вижу следующие события:

mousePressed
mouseReleased
mouseClicked

В некоторых случаях я не вижу срабатывания события mouseClicked, я вижу только:

mousePressed
mouseReleased

Я не думаю, что делаю что-то необычное, когда нажимаю в этот раз. Может ли кто-нибудь объяснить, почему я не вижу события mouseClicked?

Я не уверен, что это актуально, но у меня есть анимация, работающая на панели с использованием javax.swing.Timer.

Любая помощь приветствуется.

EDIT: добавлен тестовый код, который воспроизводит проблему. Я не уверен, но мне интересно, имеет ли к этому какое-то отношение моя мышь. У меня есть одна из тех сверхчувствительных игровых мышей (из моих старых дней COD4).

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Test {

    public static void main(String[] args) {
        final Test test = new Test();
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                test.createAndShowGUI();
            }
        });
    }

    protected void createAndShowGUI() {
        JFrame frame = new JFrame();
        frame.setPreferredSize(new Dimension(1024, 768));
        frame.setTitle("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setBackground(Color.WHITE);

        panel.addMouseListener(new MouseListener() {
            @Override
            public void mouseReleased(MouseEvent e) {
                System.out.println(":MOUSE_RELEASED_EVENT:");
            }
            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("----------------------------------\n:MOUSE_PRESSED_EVENT:");
            }
            @Override
            public void mouseExited(MouseEvent e) {
                System.out.println(":MOUSE_EXITED_EVENT:");
            }
            @Override
            public void mouseEntered(MouseEvent e) {
                System.out.println(":MOUSE_ENTER_EVENT:");
            }
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println(":MOUSE_CLICK_EVENT:");
            }
        });

        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }

}

person BillMan    schedule 01.08.2010    source источник
comment
Можете ли вы опубликовать код?   -  person Romain Hippeau    schedule 01.08.2010
comment
Просто добавил класс, который повторяет проблему. Я подумал, что, возможно, моя мышь была слишком чувствительной, и я получал события mouseMoved между событиями mousePressed и mouseReleased, но я добавил прослушиватель для mouseMoved и смог воспроизвести проблему, не видя mouseMove в середине.   -  person BillMan    schedule 01.08.2010
comment
Спасибо за этот вопрос, вместе со всеми ответами. У меня была точно такая же проблема! (Возможно, моя чувствительная мышь тоже).   -  person Hidde    schedule 21.06.2011


Ответы (5)


Согласно http://download.oracle.com/javase/tutorial/uiswing/events/mouselistener.html:

«Вы увидите событие освобождения мыши. Если вы не двигали мышь, последует событие щелчка мышью».

У меня только что была эта проблема. Если вы ВООБЩЕ переместите мышь, событие clicked не произойдет. Я действительно понятия не имею, что хорошего mouseClicked дает это знание. Я исправил это, используя mouseReleased и проверив, была ли мышь внутри объекта:

public void mouseReleased(MouseEvent e) {
    if(objectWithListener.contains(e.getPoint())){
        doClickAction();
    }
}
person Andrew    schedule 10.06.2011

Я думаю, что нашел проблему здесь. Я получал промежуточные события mouseDragged между mousePress и mouseRelease. mouseMoved, похоже, не вызывал проблемы, а вот mouseDragged вызывал.

Сейчас я не уверен в правильном решении, но, по крайней мере, теперь я могу объяснить, что происходит.

Ваше здоровье

-Счет

person BillMan    schedule 03.08.2010

Мое решение выглядит так: pointToHex сопоставляет координаты мыши с идентификатором объекта в моем представлении. Если координаты сопоставляются с одним и тем же объектом при нажатии и отпускании, я регистрирую событие щелчка.

addMouseListener(new MouseAdapter() {

            HexAddress clickedHex = null;

            public void mousePressed(MouseEvent e) {
                clickedHex = calc.pointToHex(e.getX(), e.getY());
            }

            public void mouseReleased(MouseEvent e) {
                if (clickedHex != null && clickedHex.equals(calc.pointToHex(e.getX(), e.getY()))) {
                    mapEventListener.hexClicked(clickedHex);
                    HexMapView.this.repaint();
                }
                clickedHex = null;
            }
        });
person tgdavies    schedule 09.08.2020

Пара советов тем, у кого есть такая проблема.

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

Во-вторых: у меня была проблема, когда мне нужно было jPanel (A), на котором я рисовал, установленный как макет BorderLayout.CENTER внутри другого jPanel (B), который сам был внутри jScrollPane.

Когда размер jPanel(B) был изменен, панель рисования (A) масштабировалась до правильного размера из-за менеджера компоновки BorderLayout, но (A) игнорировала любые щелчки за пределами своих первоначальных размеров, если (A) теперь больше, чем ее первоначальный размер.

Когда размер jPanel(B) был изменен, менеджер компоновки не устанавливал размеры (A) в новый размер, когда он масштабировался (A), чтобы соответствовать ЦЕНТРУ jPanel(B). Событие щелчка мыши будет срабатывать только для щелчков внутри исходных размеров jPanel (A). Мне пришлось вручную установить размер jPanel(A) в соответствии с его новыми масштабированными размерами, чтобы получить щелчки мышью для всех областей jPanel(A).

person Robbie62    schedule 25.02.2013

В тех случаях, когда все, что мне нужно, это событие clicked, я использую простое ActionListener вместо MouseListner. Событие actionPerformed, по крайней мере, для кнопок и т.п., срабатывает точно так же, как мы хотим, чтобы было событие щелчка, т. е. пока мышь находится на том же элементе управления во время отпускания, что и во время нажатия, событие actionPerformed будет уволенный.

person David    schedule 17.09.2013