Swing QuickTip: Redispatching Mouse Events(10:48, 12. Sep. 2011)

When creating a compound Swing component mouse events for embedded components will be consumed by the related component and do not reach the parent control. Alex from Sun/Oracle recently blogged about this behavior in his series 'Swing in a better world'.

Sometimes this is not the intended behavior, but Swing allows us to easily implement what we really need. As already described by Alex, one approach is to add the mouse listener to each subcomponent. Another, more transparent approach is to add another MouseListener to the subcomponent and to redispatch all events to the related parent. This is very helpful if you want to make sure that your custom component can be easily used by other developers and if you want to prevent subcomponents from being directly accessed. No public API is required - mouse handling is transparent.

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

Note: Redispatching only a few events by implementing related listener methods gives you fine granulated control on how the compound component will interact with the user.

Related Links

Swing QuickTip: Default Button
Swing QuickTip: The Totally GridBag Fix