Search code examples
javaswinglayoutjbutton

MouseMotionListener doesn't respond over JButtons


So I have a JPanel called contentPanel that holds 2 inner containers. The first is a scorePanel that holds a few buttons, a slider and a label. The other is a buttonPanel which is a grid of JButtons.

enter image description here

In my contentPanel class, I have implemented the MouseMotionListener interface and added this listener to buttonPanel called buttons.

The issue I'm having is that the mouseMoved method never gets called and I cannot get mouse coordinates while the mouse is hovering over a button. If instead I add the listener to each button, I get the mouse coordinates, but only as they relate to the origin of the button it's hovering inside of. Additionally if I add the listener to the contentPanel, I get the mouse coordinates starting from the origin of that container, but it does not trigger the event over the buttons.

Can anyone explain how to mitigate this problem and get the mouse coordinates from the origin of the button panel without JButton obstruction?

Tia.

*UPDATE: * I have made one change that has enabled the correct behavior I'm seeking, however only with a caveat. I adjusted the padding space between the buttons in the GridLayout to 15px and now when the mouse enters those in-between regions, the mouseEvent triggers. This will enable the same effect as what I seek.


Solution

  • I located some research about JButton's or other components consuming MouseEvents and not passing the event onto their parents. The solution was recommended by a member of the team at Sun/Oracle, which is to re-dispatch the event to the parent of the JComponent, which would be its container.

    This was achieved with the following code:

    JComponent subComponent = new JButton("JButton");    
    MouseAdapter redispatcher = new MouseAdapter()
    {
      @Override
      public void mouseEntered(MouseEvent evt)
      {
        dispatchMouseEvent(evt);
      }      
      @Override
      public void mouseExited(MouseEvent evt)
      {
        dispatchMouseEvent(evt);
      }
      @Override
      public void mouseMoved(MouseEvent evt)
      {
        dispatchMouseEvent(evt);
      }
      @Override
      public void mousePressed(MouseEvent evt)
      {
        dispatchMouseEvent(evt);
      }
      private void dispatchMouseEvent(MouseEvent evt)
      {
        Container parent = evt.getComponent().getParent();
        parent.dispatchEvent(SwingUtilities.convertMouseEvent(evt.getComponent(), evt, parent));
      }            
    };
    subComponent.addMouseListener(redispatcher);
    subComponent.addMouseMotionListener(redispatcher);
    

    Which was inevitably a great solution to passing events along. (http://www.jyloo.com/news/?pubId=1315817317000)