The story of one "not a bug"
Recently I came across one interesting bug 4413412 which seems to discover very odd Swing behaviors and really looks like a bug. The problem is that JLabel seems to be transparent for MouseEvents so its parent can catch mouseClick event if we click on this label. But after setting a tooltip this label stop passing MouseEvents trough and JFrame mouseListener doesn't get notified any more when we click on that label. You can check it with this little test Frame's mouse listener catches clicks from the label with no tooltip but ignores clicks from the label with tooltip. Anyway after a little investigation I closed it as not a defect.
Let's see what's going on here:
The most important thing that Swing or AWT specifications never tell that components should pass MouseEvents to their parents â€“ so JLabel with tooltip works completely according to the specification, but why having tooltip changes its behavior so visibly? It's time to discover one Swing/AWT feature which I believe should be better documented: There is the only case when component is transparent for mouse events â€“ when this component doesn't have any MouseListeners and MouseMotionListeneres attached Notice that when you do setToolTip() javax.swing.ToolTipManager adds a special MouseListener to the component to detect a moment for the tooltip to be shown. It is easy to check it using System.out.println(toolTiplabel.getMouseListeners().length); but initially JLabel doesn't have any MouseListeners â€“ that explains why JFrame's listener gets notified when we click on the first label.
Let me give some recommendations:
- Keep in mind that generally component cannot listen mouseEvents from its children.
- The only special case when it can if a child component doesn't have any MouseListeners, MouseMotionListeners and MouseWheelListeners attached, but it is not recommended to rely on this behaviour.
- There are two workarounds to make any component reacts on the MouseListener which is attached to its parent
- attach the listener from the parent to the component as well
- use AWTEventListener to catch all mouse events and filter those you need
That's how it works Alex