Search code examples
javaeventsjframemouseeventjtextarea

Why isn't mouselistener working?


Here's the code. It prints out the mouse location when it's in the panel but not the JTextArea. I added the mouse listener to the text area as well? The problem is that the coordinates are not consistent throughout the JFrame. Is there a way to just have one mouselistener that covers the entire jframe?

Is there a way to disable the mouse listener in the textarea?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;


public class test extends JFrame {

public test(){
    setPreferredSize(new Dimension(600,400));
    JPanel p = new JPanel();
    p.setBackground(Color.blue);
    p.setPreferredSize(new Dimension(600,200));
    JTextArea t = new JTextArea();
    t.setPreferredSize(new Dimension(600,200));
    add(p,BorderLayout.NORTH);
    add(t,BorderLayout.SOUTH);
    pack();
    MouseInput m = new MouseInput();
    addMouseMotionListener(m);
    t.addMouseMotionListener(m);            
    setVisible(true);

}

public static void main(String[] args){
    new test();
}
public class MouseInput implements MouseMotionListener{

    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        int mx = e.getX();
        int my = e.getY();
        System.out.println(mx + "," + my);          
    }       
}

}

Solution

  • Think of your mouse events like rain. They fall from the top of your component hierarchy down until something stops them.

    Once stopped, they will no long notify other listeners lower in the hierarchy.

    In you program you have and JPanel and JTextField sitting on top of another component (the content pane) sitting on a JLayeredPane sitting on top of the frame. Any one of these may be consuming the mouse event.

    Try adding the MouseInput to your JPanel, p instead

    Updated

    This is an example of a global mouse listener (as suggested by @Hovercraft Full Of Eels, it WILL get hammered, as every mouse event will pass through it.

    It also demonstrates how to translate a mouse point from it's local context to another context.

    import java.awt.AWTEvent;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Point;
    import java.awt.Toolkit;
    import java.awt.Window;
    import java.awt.event.AWTEventListener;
    import java.awt.event.MouseEvent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class GloablMouseListener {
    
        public static void main(String[] args) {
            new GloablMouseListener();
        }
    
        public GloablMouseListener() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new BorderLayout());
                JPanel panel = new JPanel();
                panel.setBackground(Color.BLUE);
                JTextArea ta = new JTextArea(10, 20);
                add(panel, BorderLayout.NORTH);
                add(new JScrollPane(ta), BorderLayout.SOUTH);
    
                Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                    @Override
                    public void eventDispatched(AWTEvent event) {
                        if (event instanceof MouseEvent) {
                            MouseEvent e = (MouseEvent) event;
                            System.out.println("Local point = " + e.getPoint());
                            Point p = e.getPoint();
                            Window window = SwingUtilities.getWindowAncestor(e.getComponent());
                            if (window != e.getSource() && window != null) {
                                p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), window);
                            }
                            System.out.println("Global point = " + p);
                        }
                    }
                }, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        }
    }