I have Java Swing application ToolTipMouseTest
The critical line is label.setToolTipText("label" + i);
. Once it is commented out very click on a label produces 2 mousePressed
in console. With this line enabled click on labels would produce nothing.
Is this expected behaviour or a bug? My goal is to show tooltips without disabling MouseListener
from working.
Almost SSCCE, but without imports:
public class ToolTipMouseTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ToolTipMouseTest();
}
});
}
public ToolTipMouseTest() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JLayeredPane lpane = new JLayeredPane() {
@Override
public Dimension getPreferredSize() {
return new Dimension(600,400);
}
};
MouseAdapter1 mouseAdapter1 = new MouseAdapter1();
lpane.addMouseListener(mouseAdapter1);
frame.add(lpane);
JPanel panel1 = new JPanel();
panel1.setSize(new Dimension(600, 400));
panel1.setOpaque(false);
lpane.add(panel1, JLayeredPane.PALETTE_LAYER);
JPanel panel2 = new JPanel();
for (int i = 0; i < 5; i++) {
JLabel label = new JLabel("Label " + i);
panel2.add(label);
label.setToolTipText("label" + i); //HERE!!
}
JScrollPane spane = new JScrollPane(panel2) {
private static final long serialVersionUID = 1L;
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
};
MouseAdapter2 mouseAdapter2 = new MouseAdapter2();
spane.addMouseListener(mouseAdapter2);
panel1.add(spane);
frame.pack();
frame.setVisible(true);
}
private class MouseAdapter1 extends MouseAdapter {
@Override
public void mousePressed (MouseEvent me) {
System.out.println("1 mousePressed");
}
}
private class MouseAdapter2 extends MouseAdapter {
@Override
public void mousePressed (MouseEvent me) {
System.out.println("2 mousePressed");
}
}
}
It is working as intended. Let me explain why.
When you are adding a tooltip to any component (labels in your case) they automatically recieve a new mouse listeners from ToolTipManager
. Here is the register method from ToolTipManager
class:
public void registerComponent(JComponent component) {
component.removeMouseListener(this);
component.addMouseListener(this);
component.removeMouseMotionListener(moveBeforeEnterListener);
component.addMouseMotionListener(moveBeforeEnterListener);
component.removeKeyListener(accessibilityKeyListener);
component.addKeyListener(accessibilityKeyListener);
}
When any component has atleast one mouse listener set on it - it will block any mouse enter/exit/click/press/release events (mouse dragged/moved in case there is mouse motion listener set) from going down in the components hierarchy.
In your case - labels blocking mouse events and mouse motion events from going down to layered pane due to ToolTipManager
listeners installed when tooltip is set.
This could be avoided if you make a workaround listener with that will pass events down. For example you can add that listener to every component with a tooltip that should pass mouse events down.
Here is a small example of how that could be done:
label.addMouseListener ( new MouseAdapter ()
{
public void mousePressed ( MouseEvent e )
{
lpane.dispatchEvent ( SwingUtilities.convertMouseEvent ( e.getComponent (), e, lpane ) );
}
} );
In that case event will be passed to layered pane though. Anyway you can dispatch this even anywhere you want (i guess it would be spane
in your case).
来源:https://stackoverflow.com/questions/14931323/jlabel-tooltip-interferes-with-mouselistener