简体   繁体   中英

JLabel ToolTip interferes with MouseListener

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM